蛇的控制逻辑,增长逻辑,碰撞检测改为后端实现 + 结果计分板实现
This commit is contained in:
@@ -33,7 +33,7 @@ export class GameMap extends AcGameObject {
|
||||
// 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制
|
||||
this.walls = [];
|
||||
|
||||
// 创建蛇对象数组
|
||||
// 创建蛇对象数组(可以通过 store.state.pk.game_object.snakes 全局变量调取)
|
||||
this.snakes = [
|
||||
// 注意这里的对象生成方式和传参方式
|
||||
new Snake({ id: 0, color: "#4876ec", r: this.rows - 2, c: 1 }, this),
|
||||
@@ -167,20 +167,35 @@ export class GameMap extends AcGameObject {
|
||||
this.ctx.canvas.focus();
|
||||
|
||||
// 先取出两条蛇对象
|
||||
const [snake0, snake1] = this.snakes;
|
||||
// const [snake0, snake1] = this.snakes;
|
||||
|
||||
// 获取用户信息:绑定 keydown 事件
|
||||
this.ctx.canvas.addEventListener("keydown", (e) => {
|
||||
// 取出移动的方向,需要将方向传给后端
|
||||
let d = -1; // -1 表示没有方向, 0-上, 1-右, 2-下, 3-左
|
||||
|
||||
// 定义 snake0 的键盘绑定事件
|
||||
if (e.key === "w") snake0.set_direction(0);
|
||||
else if (e.key === "d") snake0.set_direction(1);
|
||||
else if (e.key === "s") snake0.set_direction(2);
|
||||
else if (e.key === "a") snake0.set_direction(3);
|
||||
// 定义 snake1 的键盘绑定事件
|
||||
if (e.key === "w") d = 0;
|
||||
else if (e.key === "d") d = 1;
|
||||
else if (e.key === "s") d = 2;
|
||||
else if (e.key === "a") d = 3;
|
||||
|
||||
// 如果进行了合法的移动操作:向后端发送方向
|
||||
if(d>=0){
|
||||
// 使用 socket.send() 传递信息给后端,使用 JSON.stringify() 将一个 JSON 封装成一字符串
|
||||
this.store.state.pk.socket.send(JSON.stringify({
|
||||
event: "move", // 事件类型: move
|
||||
direction : d, // 方向: d
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
// 定义 snake1 的键盘绑定事件(前端调试时启用)
|
||||
else if (e.key === "ArrowUp") snake1.set_direction(0);
|
||||
else if (e.key === "ArrowRight") snake1.set_direction(1);
|
||||
else if (e.key === "ArrowDown") snake1.set_direction(2);
|
||||
else if (e.key === "ArrowLeft") snake1.set_direction(3);
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -104,11 +104,12 @@ export class Snake extends AcGameObject {
|
||||
// 这里需要使用 JSON 方法进行深度复制,以产生新的对象避免数据出错
|
||||
this.cells[i] = JSON.parse(JSON.stringify(this.cells[i - 1]));
|
||||
}
|
||||
|
||||
/* //(改为后端实现)
|
||||
// 如果下一步操作的目标位置碰撞检测不合法,则蛇直接去世
|
||||
if (!this.gamemap.check_valid(this.next_cell)) {
|
||||
this.status = "die";
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
update_move() {
|
||||
|
||||
@@ -24,8 +24,10 @@ export default {
|
||||
// 定义挂载函数,挂载完成后执行
|
||||
onMounted(() => {
|
||||
// new GameMap(canvas.value.getContext("2d"), parent.value);
|
||||
// 改为后端(服务器)获取生成地图
|
||||
new GameMap(canvas.value.getContext("2d"), parent.value, store);
|
||||
// 改为后端(服务器)获取生成地图:并将游戏信息存入 store
|
||||
store.commit("updateGameObject",
|
||||
new GameMap(canvas.value.getContext("2d"), parent.value, store),
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// 计分板
|
||||
<template>
|
||||
<div class="result-borad">
|
||||
<div class="result-board-text" v-if="$store.state.pk.loser === 'all'">
|
||||
平局!
|
||||
</div>
|
||||
<div class="result-board-text"
|
||||
v-else-if="$store.state.pk.loser === 'A' && $store.state.pk.a_id === parseInt($store.state.user.id)">
|
||||
你输了!
|
||||
</div>
|
||||
<div class="result-board-text"
|
||||
v-else-if="$store.state.pk.loser === 'B' && $store.state.pk.b_id == $store.state.user.id">
|
||||
你输了!
|
||||
</div>
|
||||
<div class="result-board-text"
|
||||
v-else-if="$store.state.pk.loser === 'A' && $store.state.pk.b_id == $store.state.user.id">
|
||||
你赢了!
|
||||
</div>
|
||||
<div class="result-board-text"
|
||||
v-else-if="$store.state.pk.loser === 'B' && $store.state.pk.a_id == $store.state.user.id">
|
||||
你赢了!
|
||||
</div>
|
||||
<div class="result-board-btn">
|
||||
<button type="button" class="btn btn-dark" @click="restart">再来一次</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useStore } from "vuex";
|
||||
|
||||
export default {
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
|
||||
// 重来,需要恢复全局变量
|
||||
const restart = () => {
|
||||
store.commit("updateStatus", "matching");
|
||||
store.commit("updateLoser", "none");
|
||||
}
|
||||
|
||||
return {
|
||||
restart,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div.result-borad {
|
||||
height: 30vh;
|
||||
width: 30vw;
|
||||
background-color: rgba(194, 194, 195, 0.504);
|
||||
/* 位置 */
|
||||
position: absolute;
|
||||
top: 30vh;
|
||||
left: 35vw;
|
||||
}
|
||||
|
||||
.result-board-text {
|
||||
text-align: center;
|
||||
color: rgb(234, 234, 234);
|
||||
font-size: 50px;
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
padding-top: 5vh;
|
||||
}
|
||||
|
||||
.result-board-btn {
|
||||
padding-top: 3vh;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -7,10 +7,20 @@ export default {
|
||||
// 对手信息
|
||||
opponent_username: "",
|
||||
opponent_photo: "",
|
||||
// 地图信息(后端传入)
|
||||
game_map: null,
|
||||
rows: 0,
|
||||
cols: 0,
|
||||
inner_walls_count: 0,
|
||||
a_id: 0,
|
||||
a_sx: 0,
|
||||
a_sy: 0,
|
||||
b_id: 0,
|
||||
b_sx: 0,
|
||||
b_sy: 0,
|
||||
// 游戏全局
|
||||
game_object: null,
|
||||
loser:"none", // all, A, B 三种结果
|
||||
},
|
||||
getters: {},
|
||||
mutations: {
|
||||
@@ -33,7 +43,20 @@ export default {
|
||||
state.rows = game_data.rows;
|
||||
state.cols = game_data.cols;
|
||||
state.inner_walls_count = game_data.inner_walls_count;
|
||||
state.a_id = game_data.a_id;
|
||||
state.a_sx = game_data.a_sx;
|
||||
state.a_sy = game_data.a_sy;
|
||||
state.b_id = game_data.b_id;
|
||||
state.b_sx = game_data.b_sx;
|
||||
state.b_sy = game_data.b_sy;
|
||||
},
|
||||
updateGameObject(state, game_object){
|
||||
// 在 GameMap.vue 中使用
|
||||
state.game_object = game_object;
|
||||
},
|
||||
updateLoser(state,loser){
|
||||
state.loser = loser;
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
module: {},
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<template>
|
||||
<PlayGround v-if="$store.state.pk.status === 'playing'" />
|
||||
<MatchGround v-else-if="$store.state.pk.status === 'matching'" />
|
||||
<ResultBoard v-if="$store.state.pk.loser !== 'none'" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlayGround from "../../components/PlayGround.vue";
|
||||
import MatchGround from "../../components/MatchGround.vue"
|
||||
import MatchGround from "../../components/MatchGround.vue";
|
||||
import ResultBoard from "../../components/ResultBoard.vue";
|
||||
|
||||
// onMounted 用于组件被挂载时, onUnmounted 用于组件被解除挂载时
|
||||
import { onMounted, onUnmounted } from "vue";
|
||||
// 取出全局变量
|
||||
@@ -14,7 +17,8 @@ import { useStore } from "vuex";
|
||||
export default {
|
||||
components: {
|
||||
PlayGround,
|
||||
MatchGround
|
||||
MatchGround,
|
||||
ResultBoard
|
||||
},
|
||||
// 创建前后端连接:当当前页面组件被加载时,建立连接,故使用 onMounted 函数
|
||||
setup() {
|
||||
@@ -23,6 +27,7 @@ export default {
|
||||
const socketUrl = `ws://127.0.0.1:3000/websocket/${store.state.user.token}/`;
|
||||
|
||||
let socket = null;
|
||||
|
||||
// 当前组件被挂载的时候,需要创建后端连接,并且需要将连接信息存储到 store 全局变量里
|
||||
onMounted(() => {
|
||||
// 定义默认匹配页面对手信息(匹配等待过程中使用)
|
||||
@@ -61,6 +66,37 @@ export default {
|
||||
store.commit("updateGameMap", data.game_data);
|
||||
console.log(data.game_data);
|
||||
}
|
||||
else if (data.event === "move") {
|
||||
// console.log(data);
|
||||
// 调取 store 中存入的地图全局信息
|
||||
const game = store.state.pk.game_object;
|
||||
// 从地图全局信息中解构出 GameMap.js 中定义的 snakes
|
||||
const [snake0, snake1] = game.snakes;
|
||||
// 设置两条蛇的移动:后端 sendMove 中的参数
|
||||
snake0.set_direction(data.a_direction);
|
||||
snake1.set_direction(data.b_direction);
|
||||
|
||||
|
||||
}
|
||||
else if (data.event === "result") {
|
||||
console.log(data);
|
||||
const game = store.state.pk.game_object;
|
||||
const [snake0, snake1] = game.snakes;
|
||||
// 修改最后一步(检测到碰撞后)蛇的眼睛方向
|
||||
snake0.eye_direction = data.a_eyes_finally_direction;
|
||||
snake1.eye_direction = data.b_eyes_finally_direction;
|
||||
|
||||
// 更新 loser 信息,存储到全局 store 中
|
||||
store.commit("updateLoser",data.loser);
|
||||
|
||||
// 更新 loser 的 snake 对象 status 状态
|
||||
if (data.loser === "all" || data.loser === "A") {
|
||||
snake0.status = "die";
|
||||
}
|
||||
if (data.loser === "all" || data.loser === "B") {
|
||||
snake1.status = "die";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket.onclose = () => {
|
||||
|
||||
Reference in New Issue
Block a user