返回
游戏创作之 Puzzle Game:Vue 实现一个拼图游戏
前端
2024-01-29 04:41:09
Puzzle Game:Vue 实现一个拼图游戏
很久之前,曾有人提议模仿鹰脚网络首页左下角那个拼图小游戏。那天晚上睡觉的时候在床上想了一下,大致 get 到了它内部实现的原理,于是就干脆动手实践一番,现在也顺道写一篇博客记录下实现思路和中间遇到的一些问题。
实现原理
以下用到了很多DOM和JS操作。Vue实例作为容器,用来盛放一个个“拼图块”组件。拼图块的每一个实例都是一个长宽相等的小正方形div,里面放一张小图片,这些小图片被随机打乱,点击其中任意一个,可以与相邻拼图块互换位置。这样一直操作,直到恢复成游戏开始时拼图图片的原貌。
1. 搭建基本结构
为了实现这个游戏,我们需要搭建一个基本的结构。这个结构包括:
- 游戏棋盘:这是一个包含所有拼图块的容器。
- 拼图块:这是游戏的基本单元。每个拼图块都是一个包含一张图片的小正方形。
- 控制拼图块移动的函数:这些函数允许玩家将拼图块移动到新的位置。
- 判断游戏是否结束的函数:这个函数检查游戏是否已经完成。
2. 创建游戏棋盘
游戏棋盘是包含所有拼图块的容器。我们可以使用 Vue.js 的 <div>
组件来创建游戏棋盘。
<div id="game-board">
<!-- 拼图块将被放置在这里 -->
</div>
3. 创建拼图块
拼图块是游戏的基本单元。每个拼图块都是一个包含一张图片的小正方形。我们可以使用 Vue.js 的 <div>
组件来创建拼图块。
<div class="puzzle-piece">
<img src="image.png" alt="拼图块图片">
</div>
4. 控制拼图块移动
我们可以使用 Vue.js 的 v-on:click
指令来控制拼图块的移动。当玩家点击一个拼图块时,该指令将触发一个函数,该函数将移动拼图块到新的位置。
<div class="puzzle-piece" v-on:click="movePiece">
<img src="image.png" alt="拼图块图片">
</div>
// 移动拼图块的函数
movePiece(event) {
// 获取被点击的拼图块
const piece = event.target;
// 获取被点击的拼图块的位置
const position = {
x: piece.offsetLeft,
y: piece.offsetTop
};
// 获取相邻的拼图块的位置
const adjacentPositions = [
{ x: position.x - 100, y: position.y },
{ x: position.x + 100, y: position.y },
{ x: position.x, y: position.y - 100 },
{ x: position.x, y: position.y + 100 }
];
// 循环相邻的拼图块,找到一个可以移动到的位置
for (const adjacentPosition of adjacentPositions) {
// 检查相邻位置是否为空
if (document.getElementById(adjacentPosition.x + ',' + adjacentPosition.y) === null) {
// 将被点击的拼图块移动到相邻位置
piece.style.left = adjacentPosition.x + 'px';
piece.style.top = adjacentPosition.y + 'px';
// 结束循环
break;
}
}
}
5. 判断游戏是否结束
我们可以使用 Vue.js 的 computed
属性来判断游戏是否结束。当游戏结束时,该属性将返回 true
,否则返回 false
。
// 判断游戏是否结束的计算属性
isGameOver() {
// 获取所有拼图块的位置
const pieces = document.querySelectorAll('.puzzle-piece');
// 循环拼图块,检查是否都已归位
for (const piece of pieces) {
// 获取拼图块的位置
const position = {
x: piece.offsetLeft,
y: piece.offsetTop
};
// 获取拼图块的正确位置
const correctPosition = {
x: piece.dataset.x,
y: piece.dataset.y
};
// 检查拼图块是否已归位
if (position.x !== correctPosition.x || position.y !== correctPosition.y) {
// 返回 false,表示游戏尚未结束
return false;
}
}
// 返回 true,表示游戏已结束
return true;
}
6. 实现游戏
现在,我们已经搭建好了游戏的基本结构,并创建了控制拼图块移动和判断游戏是否结束的函数。接下来,我们可以实现游戏了。
<div id="app">
<div id="game-board">
<puzzle-piece v-for="piece in pieces" :piece="piece" @move-piece="movePiece"></puzzle-piece>
</div>
<div v-if="isGameOver">
<h1>游戏结束!</h1>
</div>
</div>
// Vue 实例
const app = new Vue({
el: '#app',
data: {
pieces: [
{ x: 0, y: 0, image: 'image1.png' },
{ x: 100, y: 0, image: 'image2.png' },
{ x: 200, y: 0, image: 'image3.png' },
{ x: 0, y: 100, image: 'image4.png' },
{ x: 100, y: 100, image: 'image5.png' },
{ x: 200, y: 100, image: 'image6.png' },
{ x: 0, y: 200, image: 'image7.png' },
{ x: 100, y: 200, image: 'image8.png' },
{ x: 200, y: 200, image: 'image9.png' }
]
},
methods: {
movePiece(event) {
// 获取被点击的拼图块
const piece = event.target;
// 获取被点击的拼图块的位置
const position = {
x: piece.offsetLeft,
y: piece.offsetTop
};
// 获取相邻的拼图块的位置
const adjacentPositions = [
{ x: position.x - 100, y: position.y },
{ x: position.x + 100, y: position.y },
{ x: position.x, y: position.y - 100 },
{ x: position.x, y: position.y + 100 }
];
// 循环相邻的拼图块,找到一个可以移动到的位置
for (const adjacentPosition of adjacentPositions) {
// 检查相邻位置是否为空
if (document.getElementById(adjacentPosition.x + ',' + adjacentPosition.y) === null) {
// 将被点击的拼图块移动到相邻位置
piece.style.left = adjacentPosition.x + 'px';
piece.style.top = adjacentPosition.y + 'px';
// 结束循环
break;
}
}
}
},
computed: {
isGameOver() {
// 获取所有拼图块的位置
const pieces = document.querySelectorAll('.puzzle-piece');
// 循环拼图块,检查是否都已归位
for (const piece of pieces) {
// 获取拼图块的位置
const position = {
x: piece.offsetLeft,
y: piece.offsetTop
};
// 获取拼图块的正确位置
const correctPosition = {
x: piece.dataset.x,
y: piece.dataset.y
};
// 检查拼图块是否