地图改为后端生成+前端绘制
This commit is contained in:
parent
e6e6bc15e9
commit
e6c49ad600
|
@ -3,6 +3,7 @@ package com.kob.backend.consumer;
|
||||||
// WebSocket用于前后端通信
|
// WebSocket用于前后端通信
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.kob.backend.consumer.utils.Game;
|
||||||
import com.kob.backend.consumer.utils.JwtAuthenticationUtil;
|
import com.kob.backend.consumer.utils.JwtAuthenticationUtil;
|
||||||
import com.kob.backend.mapper.UserMapper;
|
import com.kob.backend.mapper.UserMapper;
|
||||||
import com.kob.backend.pojo.User;
|
import com.kob.backend.pojo.User;
|
||||||
|
@ -20,12 +21,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
@Component
|
@Component
|
||||||
@ServerEndpoint("/websocket/{token}") // 注意不要以'/'结尾
|
@ServerEndpoint("/websocket/{token}") // 注意不要以'/'结尾
|
||||||
public class WebSocketServer {
|
public class WebSocketServer {
|
||||||
// 后端向前端发送信息,首先需要创建一个 session
|
// 后端向前端发送信息,首先需要创建一个 session
|
||||||
private Session session = null;
|
private Session session = null;
|
||||||
|
// 用户信息:定义一个成员变量
|
||||||
// 用户信息:定义一个成员变量
|
|
||||||
private User user;
|
private User user;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
存储所有链接:对所有 websocket 可见的全局变量,存储为 static 静态变量
|
存储所有链接:对所有 websocket 可见的全局变量,存储为 static 静态变量
|
||||||
因为每个 websocket 实例都在一个独立的线程里,所以该公共变量应该是线程安全的
|
因为每个 websocket 实例都在一个独立的线程里,所以该公共变量应该是线程安全的
|
||||||
|
@ -33,43 +32,40 @@ public class WebSocketServer {
|
||||||
将 userId 映射到 webSocketServer
|
将 userId 映射到 webSocketServer
|
||||||
*/
|
*/
|
||||||
private static final ConcurrentHashMap<Integer, WebSocketServer> users = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Integer, WebSocketServer> users = new ConcurrentHashMap<>();
|
||||||
|
// 使用 CopyOnWriteArraySet 创建一个线程安全的匹配池 matchPool
|
||||||
// 使用 CopyOnWriteArraySet 创建一个线程安全的匹配池 matchPool
|
|
||||||
private static final CopyOnWriteArraySet<User> matchPool = new CopyOnWriteArraySet<>();
|
private static final CopyOnWriteArraySet<User> matchPool = new CopyOnWriteArraySet<>();
|
||||||
|
// 在 WebSocketServer 中注入数据库的方法演示-> 使用 static 定义为独一份的变量
|
||||||
|
|
||||||
//在 WebSocketServer 中注入数据库的方法演示-> 使用 static 定义为独一份的变量
|
|
||||||
private static UserMapper userMapper;
|
private static UserMapper userMapper;
|
||||||
|
|
||||||
// 注入方法
|
// 注入方法
|
||||||
@Autowired
|
@Autowired
|
||||||
public void setUserMapper(UserMapper userMapper) {
|
public void setUserMapper(UserMapper userMapper) {
|
||||||
// 静态变量 userMapper 访问需要使用类名 WebSocketServer 访问
|
// 静态变量 userMapper 访问需要使用类名 WebSocketServer 访问
|
||||||
WebSocketServer.userMapper = userMapper;
|
WebSocketServer.userMapper = userMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @OnOpen 创建链接时自动触发这个函数
|
// @OnOpen 创建链接时自动触发这个函数
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void onOpen(Session session, @PathParam("token") String token) throws IOException {
|
public void onOpen(Session session, @PathParam("token") String token) throws IOException {
|
||||||
// 建立链接时需要将 session 存下来
|
// 建立链接时需要将 session 存下来
|
||||||
this.session = session;
|
this.session = session;
|
||||||
// 成功建立连接时,输出 connected!
|
// 成功建立连接时,输出 connected!
|
||||||
System.out.println("backend connected!");
|
System.out.println("backend connected!");
|
||||||
// 将 userId 取出来,通过 userId 将 user 找出来
|
// 将 userId 取出来,通过 userId 将 user 找出来
|
||||||
// int userId = Integer.parseInt(token);
|
// int userId = Integer.parseInt(token);
|
||||||
int userId = JwtAuthenticationUtil.getUserId(token);
|
int userId = JwtAuthenticationUtil.getUserId(token);
|
||||||
this.user = userMapper.selectById(userId);
|
this.user = userMapper.selectById(userId);
|
||||||
|
|
||||||
// 如果 user 存在, 表示用户登录成功, 用户信息是存在的
|
// 如果 user 存在, 表示用户登录成功, 用户信息是存在的
|
||||||
if (this.user != null) {
|
if (this.user != null) {
|
||||||
// 将 user 存到 users HashMap里
|
// 将 user 存到 users HashMap里
|
||||||
users.put(userId, this);
|
users.put(userId, this);
|
||||||
|
|
||||||
// (测试)后台输出看用户信息
|
// (测试)后台输出看用户信息
|
||||||
// System.out.println(user);
|
// System.out.println(user);
|
||||||
}
|
}
|
||||||
// 否则,断开连接(这里需要抛出异常)
|
// 否则,断开连接(这里需要抛出异常)
|
||||||
else {
|
else {
|
||||||
this.session.close();
|
this.session.close();
|
||||||
}
|
}
|
||||||
|
@ -81,25 +77,25 @@ public class WebSocketServer {
|
||||||
public void onClose() {
|
public void onClose() {
|
||||||
// 关闭链接
|
// 关闭链接
|
||||||
System.out.println("backend disconnected!");
|
System.out.println("backend disconnected!");
|
||||||
// 断开连接时,需要将 user 从 users 里面删掉
|
// 断开连接时,需要将 user 从 users 里面删掉
|
||||||
if (this.user != null) {
|
if (this.user != null) {
|
||||||
users.remove(this.user.getId());
|
users.remove(this.user.getId());
|
||||||
// 将匹配池数组删掉
|
// 将匹配池数组删掉
|
||||||
matchPool.remove(this.user);
|
matchPool.remove(this.user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @OnMessage 用于从前端接收请求: 一般 onMessage 当成路由使用,做为消息判断处理的中间部分
|
// @OnMessage 用于从前端接收请求: 一般 onMessage 当成路由使用,做为消息判断处理的中间部分
|
||||||
@OnMessage
|
@OnMessage
|
||||||
public void onMessage(String message, Session session) {
|
public void onMessage(String message, Session session) {
|
||||||
// 从 Client 接收消息
|
// 从 Client 接收消息
|
||||||
System.out.println("receive message");
|
System.out.println("receive message");
|
||||||
// 解析从前端接收到的请求
|
// 解析从前端接收到的请求
|
||||||
JSONObject data = JSONObject.parseObject(message);
|
JSONObject data = JSONObject.parseObject(message);
|
||||||
String event = data.getString("event");
|
String event = data.getString("event");
|
||||||
// System.out.println(event);
|
// System.out.println(event);
|
||||||
|
|
||||||
// 匹配状态函数调用
|
// 匹配状态函数调用
|
||||||
if ("start-matching".equals(event)) {
|
if ("start-matching".equals(event)) {
|
||||||
startMatching();
|
startMatching();
|
||||||
} else if ("stop-matching".equals(event)) {
|
} else if ("stop-matching".equals(event)) {
|
||||||
|
@ -112,12 +108,12 @@ public class WebSocketServer {
|
||||||
error.printStackTrace();
|
error.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从后端向前端发送信息
|
// 从后端向前端发送信息
|
||||||
public void sendMessage(String message) {
|
public void sendMessage(String message) {
|
||||||
// 异步通信过程,先加一个锁
|
// 异步通信过程,先加一个锁
|
||||||
synchronized (this.session) {
|
synchronized (this.session) {
|
||||||
try {
|
try {
|
||||||
// 将 message 发送到前端
|
// 将 message 发送到前端
|
||||||
this.session.getBasicRemote().sendText(message);
|
this.session.getBasicRemote().sendText(message);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -125,37 +121,43 @@ public class WebSocketServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始匹配的逻辑部分
|
// 开始匹配的逻辑部分
|
||||||
private void startMatching() {
|
private void startMatching() {
|
||||||
System.out.println("start matching");
|
System.out.println("start matching");
|
||||||
matchPool.add(this.user);
|
matchPool.add(this.user);
|
||||||
|
|
||||||
while (matchPool.size()>=2){
|
while (matchPool.size()>=2){
|
||||||
// 迭代器用于枚举前两个人进行匹配
|
// 迭代器用于枚举前两个人进行匹配
|
||||||
Iterator<User> it = matchPool.iterator();
|
Iterator<User> it = matchPool.iterator();
|
||||||
User a = it.next(), b = it.next();
|
User a = it.next(), b = it.next();
|
||||||
// 取出两个人之后,从匹配池中将他们删除
|
// 取出两个人之后,从匹配池中将他们删除
|
||||||
matchPool.remove(a);
|
matchPool.remove(a);
|
||||||
matchPool.remove(b);
|
matchPool.remove(b);
|
||||||
|
|
||||||
// 将 a 配对成功的消息传回客户端
|
// 匹配成功时,创建联机地图
|
||||||
|
Game game = new Game(13,14,20);
|
||||||
|
game.createMap(); // 初始化地图
|
||||||
|
|
||||||
|
// 将 a 配对成功的消息传回客户端
|
||||||
JSONObject respA = new JSONObject();
|
JSONObject respA = new JSONObject();
|
||||||
respA.put("event","start-matching");
|
respA.put("event","start-matching");
|
||||||
respA.put("opponent_username",b.getUsername());
|
respA.put("opponent_username",b.getUsername());
|
||||||
respA.put("opponent_photo",b.getPhoto());
|
respA.put("opponent_photo",b.getPhoto());
|
||||||
// 获取 a 的链接,并通过 sendMessage 将消息传给前端
|
respA.put("game_map",game.getG());
|
||||||
|
// 获取 a 的链接,并通过 sendMessage 将消息传给前端
|
||||||
users.get(a.getId()).sendMessage(respA.toJSONString());
|
users.get(a.getId()).sendMessage(respA.toJSONString());
|
||||||
|
|
||||||
// 同理,将 b 的匹配成功信息传回给前端
|
// 同理,将 b 的匹配成功信息传回给前端
|
||||||
JSONObject respB = new JSONObject();
|
JSONObject respB = new JSONObject();
|
||||||
respB.put("event","start-matching");
|
respB.put("event","start-matching");
|
||||||
respB.put("opponent_username",a.getUsername());
|
respB.put("opponent_username",a.getUsername());
|
||||||
respB.put("opponent_photo",a.getPhoto());
|
respB.put("opponent_photo",a.getPhoto());
|
||||||
|
respB.put("game_map",game.getG());
|
||||||
users.get(b.getId()).sendMessage(respB.toJSONString());
|
users.get(b.getId()).sendMessage(respB.toJSONString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消匹配的逻辑部分
|
// 取消匹配的逻辑部分
|
||||||
private void stopMatching() {
|
private void stopMatching() {
|
||||||
System.out.println("stop matching");
|
System.out.println("stop matching");
|
||||||
matchPool.remove(this.user);
|
matchPool.remove(this.user);
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package com.kob.backend.consumer.utils;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// 用来管理整个游戏流程
|
||||||
|
public class Game {
|
||||||
|
// 游戏地图:行数,列数,内部障碍物数量
|
||||||
|
private final Integer rows;
|
||||||
|
private final Integer cols;
|
||||||
|
private final Integer inner_walls_count;
|
||||||
|
// 地图数组
|
||||||
|
private final int[][] g;
|
||||||
|
// 定义"上右下左"四个方向的 dx, dy偏移量
|
||||||
|
private final int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
|
||||||
|
|
||||||
|
// 初始化构造函数
|
||||||
|
public Game(Integer rows, Integer cols, Integer inner_walls_count) {
|
||||||
|
this.rows = rows;
|
||||||
|
this.cols = cols;
|
||||||
|
this.inner_walls_count = rows;
|
||||||
|
this.g = new int[rows][cols];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回生成的地图
|
||||||
|
public int[][] getG() {
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画地图
|
||||||
|
public boolean draw() {
|
||||||
|
// 一开始现将所有障碍物初始化为 false
|
||||||
|
for (int r = 0; r < this.rows; r++) {
|
||||||
|
for (int c = 0; c < this.cols; c++) {
|
||||||
|
// 0 表示空地, 1 表示障碍物(墙)
|
||||||
|
g[r][c] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 地图左右边缘障碍物
|
||||||
|
for (int r = 0; r < this.rows; r++) {
|
||||||
|
g[r][0] = g[r][this.cols - 1] = 1;
|
||||||
|
}
|
||||||
|
// 地图上下边缘障碍物
|
||||||
|
for (int c = 0; c < this.cols; c++) {
|
||||||
|
g[0][c] = g[this.rows - 1][c] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
// 创建内部随机障碍物,每次计算时会生成两个障碍物,因此这里的循环次数 this.inner_walls_count 需要处以 2
|
||||||
|
for (int i = 0; i < this.inner_walls_count / 2; i++) {
|
||||||
|
// 避免位置重复:重复遍历 1000 次,只要找到了已经存在障碍物的位置就禁止随机
|
||||||
|
for (int j = 0; j < 1000; j++) {
|
||||||
|
// 找出本次随机到的行-r 列-c 坐标
|
||||||
|
int r = random.nextInt(this.rows); // random.nextInt(7) 返回 0-7之间的随机整数
|
||||||
|
int c = random.nextInt(this.cols);
|
||||||
|
|
||||||
|
// 中心对称:当本坐标或者它的中心对称坐标已经存在障碍物了,则重新计算下一个坐标
|
||||||
|
if (g[r][c] == 1 || g[this.rows - 1 - r][this.cols - 1 - c] == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 避免内部障碍物覆盖掉左下角和右上角的 A-B 角色出发点,如果是这两个位置,则重新计算下一个坐标
|
||||||
|
if (r == this.rows - 2 && c == 1 || r == 1 && c == this.cols - 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 将计算求得的随机障碍物合法的位置赋值为 1 ,以对该位置进行绘制(包括本坐标及其中心对称坐标)
|
||||||
|
g[r][c] = g[this.rows - 1 - r][this.cols - 1 - c] = 1;
|
||||||
|
|
||||||
|
// 1000 次遍历中,规定数量的内部障碍物已经够数之后就 break 掉
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保 A-B 角色的运动区域是联通的:如果不连通,则直接在创建地图对象之前取消绘制( return false )
|
||||||
|
return check_connectivity(this.rows - 2, 1, 1, this.cols - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 联通检测方法---true(联通)---false(不通),参数: 起点坐标 sx,sy ,终点坐标 tx,ty
|
||||||
|
private boolean check_connectivity(int sx, int sy, int tx, int ty) {
|
||||||
|
// 起点就是终点时,结果联通,直接返回 true
|
||||||
|
if (sx == tx && sy == ty) return true;
|
||||||
|
g[sx][sy] = 1;
|
||||||
|
|
||||||
|
//枚举"上右下左"四个方向,求当前点下一个相邻点的坐标
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int x = sx + dx[i];
|
||||||
|
int y = sy + dy[i];
|
||||||
|
|
||||||
|
// 判断是否撞到障碍物( g[x][y] == 0 表示没有碰到障碍物 ),如果没有赚到障碍物,且可以找到重点的话,返回 true(联通)
|
||||||
|
if (x >= 0 && x < this.rows && y >= 0 && y < this.cols && g[x][y] == 0) {
|
||||||
|
if (check_connectivity(x, y, tx, ty)) {
|
||||||
|
// 还原状态
|
||||||
|
g[sx][sy] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 还原状态
|
||||||
|
g[sx][sy] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createMap() {
|
||||||
|
// 循环绘制:如果发现哪次循环中画地图成功了,则跳出循环,绘制结束
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
if (draw())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,24 +7,26 @@ import { Wall } from "./Wall";
|
||||||
// 导出定义的 GameMap 游戏地图类
|
// 导出定义的 GameMap 游戏地图类
|
||||||
export class GameMap extends AcGameObject {
|
export class GameMap extends AcGameObject {
|
||||||
// 构造函数参数: ctx 画布; parent 画布的父元素,用来动态修改画布的长宽
|
// 构造函数参数: ctx 画布; parent 画布的父元素,用来动态修改画布的长宽
|
||||||
constructor(ctx, parent) {
|
constructor(ctx, parent, store) {
|
||||||
// super() 用于先执行基类的构造函数
|
// super() 用于先执行基类的构造函数
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// 存下 ctx 和 parent
|
// 存下 ctx 和 parent
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
this.store = store;
|
||||||
|
|
||||||
// 存下每个格子的绝对距离
|
// 存下每个格子的绝对距离
|
||||||
this.L = 0;
|
this.L = 0;
|
||||||
|
|
||||||
// 定义棋盘格的行数和列数
|
/*
|
||||||
|
// 定义棋盘格的行数和列数(前端生成地图时使用)
|
||||||
// 行数和列数不同时设置为偶数或者不同时设置为奇数,可以避免AB两蛇同时进入同一个格子,避免因此对优势者不公平
|
// 行数和列数不同时设置为偶数或者不同时设置为奇数,可以避免AB两蛇同时进入同一个格子,避免因此对优势者不公平
|
||||||
this.rows = 13;
|
this.rows = 13;
|
||||||
this.cols = 14;
|
this.cols = 14;
|
||||||
|
// 绘制棋盘内部区域的障碍物(墙)的数量(前端生成地图时使用)
|
||||||
// 绘制棋盘内部区域的障碍物(墙)的数量
|
this.inner_walls_count = 30;
|
||||||
this.inner_walls_count = 20;
|
*/
|
||||||
|
|
||||||
// 存储所有的墙
|
// 存储所有的墙
|
||||||
// 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制
|
// 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制
|
||||||
|
@ -38,7 +40,8 @@ export class GameMap extends AcGameObject {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标
|
/*
|
||||||
|
// 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标(前端生成地图时使用)
|
||||||
check_connectivity(g, sx, sy, tx, ty) {
|
check_connectivity(g, sx, sy, tx, ty) {
|
||||||
// 当起点坐标和中点坐标一致时,判断联通,直接返回
|
// 当起点坐标和中点坐标一致时,判断联通,直接返回
|
||||||
if (sx == tx && sy == ty) return true;
|
if (sx == tx && sy == ty) return true;
|
||||||
|
@ -58,8 +61,31 @@ export class GameMap extends AcGameObject {
|
||||||
// 搜不到终点,返回 false
|
// 搜不到终点,返回 false
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// 创建墙函数
|
// 创建障碍物(后端生成地图版本)
|
||||||
|
create_wall() {
|
||||||
|
// 取出后端生成后传到前端 store 中的 game_map
|
||||||
|
const g = this.store.state.pk.game_map;
|
||||||
|
|
||||||
|
|
||||||
|
// 枚举数组,将 g[r][c] == true 的部分绘制出来
|
||||||
|
// 如果上一步连通性检测失败,则退出 this.create_wall() 函数,本步骤不再执行生成新对象的操作
|
||||||
|
for (let r = 0; r < this.rows; r++) {
|
||||||
|
for (let c = 0; c < this.cols; c++) {
|
||||||
|
if (g[r][c]) {
|
||||||
|
// 将每个新生成的 Wall 对象 push 存入 walls 数组中
|
||||||
|
this.walls.push(new Wall(r, c, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制成功则 return turn
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 创建障碍物(前端计算地图版本)
|
||||||
create_wall() {
|
create_wall() {
|
||||||
// 创建一个墙格进行测试
|
// 创建一个墙格进行测试
|
||||||
// new Wall(0,0,this);
|
// new Wall(0,0,this);
|
||||||
|
@ -134,6 +160,7 @@ export class GameMap extends AcGameObject {
|
||||||
// 绘制成功则 return turn
|
// 绘制成功则 return turn
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// 添加监听:用于绑定键盘输入,以便获取用户操作控制蛇
|
// 添加监听:用于绑定键盘输入,以便获取用户操作控制蛇
|
||||||
add_listening_events() {
|
add_listening_events() {
|
||||||
|
@ -160,9 +187,12 @@ export class GameMap extends AcGameObject {
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
// 开始时调用一次创建墙的函数
|
// 开始时调用一次创建墙的函数
|
||||||
// 循环 1000 次,如果成功创建则 break ,否则继续循环创建
|
// 循环 1000 次,如果成功创建则 break ,否则继续循环创建(前端生成地图时使用这一条)
|
||||||
for (let i = 0; i < 1000; i++) if (this.create_wall()) break;
|
// for (let i = 0; i < 1000; i++) if (this.create_wall()) break;
|
||||||
|
|
||||||
|
// 使用后端生成地图时,这里只需要调用一次就好
|
||||||
|
this.create_wall();
|
||||||
|
|
||||||
// 开始时启动监听方法
|
// 开始时启动监听方法
|
||||||
this.add_listening_events();
|
this.add_listening_events();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,20 @@
|
||||||
import { GameMap } from "@/assets/scripts/GameMap";
|
import { GameMap } from "@/assets/scripts/GameMap";
|
||||||
// 引入 canvas, onMounted 用于挂载操作定义
|
// 引入 canvas, onMounted 用于挂载操作定义
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
|
const store = useStore();
|
||||||
// 定义两个变量 parent 和 canvas, 一开始这两个变量都没有指向任何元素,因此 ref(null)
|
// 定义两个变量 parent 和 canvas, 一开始这两个变量都没有指向任何元素,因此 ref(null)
|
||||||
let parent = ref(null);
|
let parent = ref(null);
|
||||||
let canvas = ref(null);
|
let canvas = ref(null);
|
||||||
|
|
||||||
// 定义挂载函数,挂载完成后执行
|
// 定义挂载函数,挂载完成后执行
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
new GameMap(canvas.value.getContext("2d"), parent.value);
|
// new GameMap(canvas.value.getContext("2d"), parent.value);
|
||||||
|
// 改为后端(服务器)获取生成地图
|
||||||
|
new GameMap(canvas.value.getContext("2d"), parent.value, store);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -7,6 +7,7 @@ export default {
|
||||||
// 对手信息
|
// 对手信息
|
||||||
opponent_username: "",
|
opponent_username: "",
|
||||||
opponent_photo: "",
|
opponent_photo: "",
|
||||||
|
game_map: null,
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
@ -23,6 +24,10 @@ export default {
|
||||||
updateStatus(state, status) {
|
updateStatus(state, status) {
|
||||||
state.status = status;
|
state.status = status;
|
||||||
},
|
},
|
||||||
|
// 更新地图
|
||||||
|
updateGameMap(state,game_map){
|
||||||
|
state.game_map = game_map;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions: {},
|
actions: {},
|
||||||
module: {},
|
module: {},
|
||||||
|
|
|
@ -42,6 +42,7 @@ export default {
|
||||||
store.commit("updateSocket", socket);
|
store.commit("updateSocket", socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从后端传过来的数据信息
|
||||||
socket.onmessage = (msg) => {
|
socket.onmessage = (msg) => {
|
||||||
const data = JSON.parse(msg.data);
|
const data = JSON.parse(msg.data);
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
|
@ -56,6 +57,8 @@ export default {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
store.commit("updateStatus", "playing");
|
store.commit("updateStatus", "playing");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
// 匹配成功,从后端更新地图
|
||||||
|
store.commit("updateGameMap",data.game_map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue