地图改为后端生成+前端绘制

This commit is contained in:
2023-02-27 23:01:11 +08:00
parent e6e6bc15e9
commit e6c49ad600
6 changed files with 198 additions and 44 deletions
+39 -9
View File
@@ -7,24 +7,26 @@ import { Wall } from "./Wall";
// 导出定义的 GameMap 游戏地图类
export class GameMap extends AcGameObject {
// 构造函数参数: ctx 画布; parent 画布的父元素,用来动态修改画布的长宽
constructor(ctx, parent) {
constructor(ctx, parent, store) {
// super() 用于先执行基类的构造函数
super();
// 存下 ctx 和 parent
this.ctx = ctx;
this.parent = parent;
this.store = store;
// 存下每个格子的绝对距离
this.L = 0;
// 定义棋盘格的行数和列数
/*
// 定义棋盘格的行数和列数(前端生成地图时使用)
// 行数和列数不同时设置为偶数或者不同时设置为奇数,可以避免AB两蛇同时进入同一个格子,避免因此对优势者不公平
this.rows = 13;
this.cols = 14;
// 绘制棋盘内部区域的障碍物(墙)的数量
this.inner_walls_count = 20;
// 绘制棋盘内部区域的障碍物(墙)的数量(前端生成地图时使用)
this.inner_walls_count = 30;
*/
// 存储所有的墙
// 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制
@@ -38,7 +40,8 @@ export class GameMap extends AcGameObject {
];
}
// 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标
/*
// 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标(前端生成地图时使用)
check_connectivity(g, sx, sy, tx, ty) {
// 当起点坐标和中点坐标一致时,判断联通,直接返回
if (sx == tx && sy == ty) return true;
@@ -58,8 +61,31 @@ export class GameMap extends AcGameObject {
// 搜不到终点,返回 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() {
// 创建一个墙格进行测试
// new Wall(0,0,this);
@@ -134,6 +160,7 @@ export class GameMap extends AcGameObject {
// 绘制成功则 return turn
return true;
}
*/
// 添加监听:用于绑定键盘输入,以便获取用户操作控制蛇
add_listening_events() {
@@ -160,9 +187,12 @@ export class GameMap extends AcGameObject {
start() {
// 开始时调用一次创建墙的函数
// 循环 1000 次,如果成功创建则 break ,否则继续循环创建
for (let i = 0; i < 1000; i++) if (this.create_wall()) break;
// 循环 1000 次,如果成功创建则 break ,否则继续循环创建(前端生成地图时使用这一条)
// for (let i = 0; i < 1000; i++) if (this.create_wall()) break;
// 使用后端生成地图时,这里只需要调用一次就好
this.create_wall();
// 开始时启动监听方法
this.add_listening_events();
}
+5 -1
View File
@@ -12,16 +12,20 @@
import { GameMap } from "@/assets/scripts/GameMap";
// 引入 canvas, onMounted 用于挂载操作定义
import { ref, onMounted } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
// 定义两个变量 parent 和 canvas, 一开始这两个变量都没有指向任何元素,因此 ref(null)
let parent = ref(null);
let canvas = ref(null);
// 定义挂载函数,挂载完成后执行
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 {
+5
View File
@@ -7,6 +7,7 @@ export default {
// 对手信息
opponent_username: "",
opponent_photo: "",
game_map: null,
},
getters: {},
mutations: {
@@ -23,6 +24,10 @@ export default {
updateStatus(state, status) {
state.status = status;
},
// 更新地图
updateGameMap(state,game_map){
state.game_map = game_map;
}
},
actions: {},
module: {},
+3
View File
@@ -42,6 +42,7 @@ export default {
store.commit("updateSocket", socket);
}
// 从后端传过来的数据信息
socket.onmessage = (msg) => {
const data = JSON.parse(msg.data);
// console.log(data);
@@ -56,6 +57,8 @@ export default {
setTimeout(() => {
store.commit("updateStatus", "playing");
}, 2000);
// 匹配成功,从后端更新地图
store.commit("updateGameMap",data.game_map)
}
}