使用Vue框架开发的贪吃蛇小游戏
VUE2.0开发的贪吃蛇
·
注意:尽量不要用谷歌浏览器运行,因为谷歌浏览器会把GameValue翻译成中文,使游戏掉帧卡顿
解决办法:1.使用Edge浏览器,2.把谷歌浏览器的自动中文翻译关闭即可
游戏截图:
源码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" content="width=device-width,initial-scale=1.0,user-scalable=0" name="viewport">
<title>贪吃蛇</title>
<link href="https://llh317.oss-cn-guangzhou.aliyuncs.com/bootstrap-4.6.1-dist/bootstrap-4.6.1-dist/css/bootstrap.min.css"
rel="stylesheet">
<script src="https://llh317.oss-cn-guangzhou.aliyuncs.com/js-package/js/vue.js"></script>
<style>
* {
user-select: none;
}
.mapParent {
height: 500px;
}
.map {
border: 1px red dashed;
height: 100%;
width: 100%;
}
.titleAlert {
font-weight: bold;
}
.system {
color: #909399;
font-size: 12px;
}
.titleValue {
font-size: 12px;
color: #909399;
margin: -10px 0;
}
.foot {
text-align: center;
}
.butWASD button {
font-size: 50px;
width: 150px;
height: 150px;
}
.hereto {
color: #909399;
margin: 0 5px;
text-decoration: underline;
}
.description {
font-size: 16px;
color: #909399;
}
.footNote {
font-size: 12px;
color: #909399;
}
.sbody {
background-color: skyblue;
}
.shead {
background-color: red;
}
.food {
background-color: blueviolet;
}
</style>
</head>
<body>
<div class="llh">
<br>
<br>
<div @keydown.65="aKey"
@keydown.68="dKey"
@keydown.75="accelerate(true)"
@keydown.83="sKey"
@keydown.87="wKey"
@keydown.down="sKey"
@keydown.left="aKey"
@keydown.right="dKey"
@keydown.up="wKey"
@keyup.74="gameState(2)"
@keyup.75="accelerate(false)"
class="container" id="v1">
<div class="row">
<div class="col-sm-3" style="text-align: center;">
<button :class="{
btn:true,
'btn-info':buttonColorNum===0,
'btn-success':buttonColorNum===1,
'btn-danger':buttonColorNum===2,
'btn-warning':buttonColorNum===3
}" @blur="gameState(1)" @click="gameState(0)">{{buttonPrompt}}
</button>
<br><br>
<h3 style="color: #303133;">得分:{{score}}</h3>
<h6 class="titleAlert" id="open" style="color: blue;display: none;">[ 已启动加速 ]</h6>
<h6 class="titleAlert" id="close" style="color: red;">[ 已关闭加速 ]</h6>
</div>
<div class="col-sm-6 mapParent">
<table align="center" class="map" v-html="gameMapData"></table>
</div>
<div class="col-sm-3 system">
<label class="titleValue">游戏参数调试板:</label>
<br>
<label class="titleValue">score:~~~</label>{{score}}
<br>
<label class="titleValue">snakeLength:~~~</label>{{snakeLength}}
<br>
<label class="titleValue">xSnake:~~~</label>{{xSnake}}
<br>
<label class="titleValue">ySnake:~~~</label>{{ySnake}}
<br>
<label class="titleValue">xTimerLog:~~~</label>{{xTimerLog}}
<br>
<label class="titleValue">yTimerLog:~~~</label>{{yTimerLog}}
<br>
<label class="titleValue">playerDirection:~~~</label>{{playerDirection}}
<br>
<label class="titleValue">X-Y:</label>{{walkList}}
</div>
</div>
<br>
<div>
<div class="foot">
<div class="butWASD" v-if="butWASD">
<button @click="wKey" class="btn btn-danger">上</button>
<br>
<button @click="aKey" class="btn btn-danger">左</button>
<button class="btn"></button>
<button @click="dKey" class="btn btn-danger">右</button>
<br>
<button @click="sKey" class="btn btn-danger">下</button>
</div>
<hr>
<div class="description">
操作:( W-A-S-D:方向 )-(暂停/开始游戏:j )-( 加速:k )-(如果游戏出现停止运行,重新点击按钮即可)
</div>
<hr>
<div class="footNote">
Creation time 2021-10-01
<a class="hereto" href="https://blog.csdn.net/L0317">©廖利辉</a>
<a class="hereto"
href="https://blog.csdn.net/L0317/article/details/122098926?spm=1001.2014.3001.5501">®TCS</a>
<a class="hereto" href="https://cn.vuejs.org/index.html">™VUE.JS-version:2.0</a>
</div>
</div>
</div>
<br>
</div>
</div>
</body>
<script>
new Vue({
el: "#v1",
data: {
/* 按钮样式 */
buttonColorNum: -1, //按钮颜色
buttonPrompt: "", //按钮提示
/* 绘制地图 */
gameMapData: "", //地图的html数据
dituSize: 100, //地图的大小
/* 游戏参数(管远缘量身定做) */
speed: 70, //速度
speedMirroring: 0, //速度镜像
score: 0, //得分
snakeLength: 10, //蛇身长度
/* 游戏日志 */
walkList: [], //行走记录
xSnake: 0, //横向
ySnake: 0, //纵向
xFood: 0, //食物横向
yFood: 0, //食物纵向
playerDirection: 0, //保存方向
/* 计时器 */
xTimerLog: null, //横向计时器
yTimerLog: null, //纵向计时器
/* 手机端按钮 */
butWASD: false
},
methods: {
accelerate(bool) {
//加速
this.speed = bool ? 20 : this.speedMirroring
this.getllh("open").style.display = bool ? "block" : "none"
this.getllh("close").style.display = bool ? "none" : "block"
},
gameState(state) {
//0运行 1游戏意外停止(游戏指针转移) 2暂停
//处理重复手动点击
if (state === 0 && this.buttonColorNum === 1) {
state = 2
}
//处理暂停状态时按j
if (state === 2 && this.buttonColorNum === 3) {
state = 0
}
//处理停止状态时按j
if (state === 2 && this.buttonColorNum === 2) {
state = 0
}
if (state === 0) {
/* 游戏开始 */
this.buttonPrompt = "游戏正在运行";
this.buttonColorNum = 1
/* 初始化 */
if (this.xSnake === 0 && this.xFood === 0) {
//保持从中间出来
this.ySnake = this.xSnake = Math.floor(this.dituSize / 2);
this.setFood(); //随机产生豆子
} else {
//启动后,重新启动保持方向
if (this.xTimerLog != null && this.playerDirection > 0) {
this.xTimerLog = null; //设置为空,方向改变器
this.dKey();
} else if (this.xTimerLog != null && this.playerDirection < 0) {
this.xTimerLog = null; //设置为空,方向改变器
this.aKey();
} else if (this.yTimerLog != null && this.playerDirection > 0) {
this.yTimerLog = null; //设置为空,方向改变器
this.sKey();
} else if (this.yTimerLog != null && this.playerDirection < 0) {
this.yTimerLog = null; //设置为空,方向改变器
this.wKey();
}
}
} else if (state === 1) {
// PC端需要聚焦到开始按钮,手机端不需要
if (!this.butWASD) {
/* 游戏停止 */
this.buttonPrompt = "游戏停止运行(继续运行)";
this.buttonColorNum = 2;
// 清空计时器
this.xTimerLog != null ? clearInterval(this.xTimerLog) : ""
this.yTimerLog != null ? clearInterval(this.yTimerLog) : ""
}
} else if (state === 2) {
/* 游戏暂停 */
this.buttonPrompt = "游戏暂停运行(开始游戏)";
this.buttonColorNum = 3;
//清空计时器
this.xTimerLog != null ? clearInterval(this.xTimerLog) : ""
this.yTimerLog != null ? clearInterval(this.yTimerLog) : ""
}
},
wKey() {
this.direction("y", -1); //y轴减少
},
aKey() {
this.direction("x", -1); //x轴减少
},
sKey() {
this.direction("y", 1); //y轴增多
},
dKey() {
this.direction("x", 1); //x轴增多
},
direction(axis, num) {
/* 方向改变器 */
//游戏必须处于运行状态
if (this.buttonColorNum === 1) {
if (axis === "x") {
/* x轴运动器 */
//x轴计时器必须为空
if (this.xTimerLog == null) {
if (this.yTimerLog != null) this.initializeTimer("y") //初始化y
this.playerDirection = num; //保存玩家的方向
this.xTimerLog = setInterval(() => {
this.xSnake += num //x加1
this.addWalkList(this.xSnake, this.ySnake); //保存记录
this.walkStart(); //行走
}, this.speed)
}
} else if (axis === "y") {
/* y轴运动器 */
if (this.yTimerLog == null) {
if (this.xTimerLog) this.initializeTimer("x") //初始化x
this.playerDirection = num; //保存玩家的方向
this.yTimerLog = setInterval(() => {
this.ySnake += num //y加1
this.addWalkList(this.xSnake, this.ySnake); //保存记录
this.walkStart(); //行走
}, this.speed)
}
}
}
},
addWalkList(x, y) {
/* 记录保存器 */
function Log(xLog, yLog) { //日志对象
this.xLog = xLog;
this.yLog = yLog;
}
this.walkList[this.walkList.length] = new Log(x, y); //当前记录添加进去
/* 性能优化(数组长度根据蛇的长度+1去定制) +1是为了获取被清空的那个一格*/
let performance = [];
if (this.walkList.length > this.snakeLength) {
/* 截取蛇身长度的数值优化 */
for (let i = this.walkList.length - 1 - this.snakeLength; i <= this.walkList.length -
1; i++) {
performance[performance.length] = this.walkList[i];
}
this.walkList = performance;
}
},
walkStart() {
/* 行走器 */
let headObj = this.walkList[this.walkList.length - 1]; //读取玩家头记录
this.sStyle(headObj.xLog, headObj.yLog, true, "shead"); //设置头
let bodyObj = this.walkList[this.walkList.length - 2]; //读取玩家身体记录
if (bodyObj != null) this.sStyle(bodyObj.xLog, bodyObj.yLog, true, "sbody") //设置身体
let clearObj = this.walkList[this.walkList.length - 1 - this.snakeLength]; //读取清空的记录
if (clearObj != null) this.sStyle(clearObj.xLog, clearObj.yLog, false) //清空身体
if (headObj.xLog === this.xFood && headObj.yLog === this.yFood) { //判断头部,是否触碰了食物
this.score += 1; //加一分
if (this.score % 2 === 0) this.snakeLength += 1 //2个豆子一格身子
this.setFood(); //随机产生食物
}
for (let i = 0; i <= this.walkList.length - 2; i++) { //遍历身体,判断头部是否触碰到身体
if (this.walkList[i].xLog === headObj.xLog && this.walkList[i].yLog === headObj.yLog) {
location.reload()
alert("游戏结束")
}
}
},
setFood() {
/* 食物放置器 */
this.xFood = Math.floor(Math.random() * this.dituSize); //食物的x轴
this.yFood = Math.floor(Math.random() * this.dituSize); //食物的y轴
this.sStyle(this.xFood, this.yFood, true, "food"); //给食物添加样式
},
initializeTimer(axis) {
/* 计时初始化器 */
if (axis === "x") {
if (this.xTimerLog != null) {
clearInterval(this.xTimerLog)
this.xTimerLog = null;
}
} else if (axis === "y") {
if (this.yTimerLog != null) {
clearInterval(this.yTimerLog)
this.yTimerLog = null;
}
}
},
sStyle(x, y, bool, className) {
/* 样式改变器*/
try {
if (bool) {
/* 设置样式 */
this.getllh("llh-" + x + "-" + y).className = className;
} else {
/* 清空样式 */
this.getllh("llh-" + x + "-" + y).className = "";
}
} catch (exception) {
location.reload()
alert("游戏结束")
}
},
getllh(name) {
/* 元素获取器 */
return document.getElementById(name);
},
isPC() {
// 是否为PC端
let sUserAgent = navigator.userAgent.toLowerCase();
return !/ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test(sUserAgent);
}
},
created() {
/* 初始化地图 */
console.log(
`%c 贪吃蛇 %c 作者:廖利辉 %c `,
'background:#35495e ; padding: 1px; border-radius: 3px 0 0 3px; color: #fff',
'background:#41b883 ; padding: 1px; border-radius: 0 3px 3px 0; color: #fff',
'background:transparent'
)
this.buttonPrompt = "地图渲染中"; // 改变按钮文字
let size = this.dituSize; // 获取地图的参数
/* 循环y轴 */
for (let y = 0; y < size; y++) {
this.gameMapData += "<tr>";
/* 循环x轴 */
for (let x = 0; x < size; x++) {
this.gameMapData += "<td id='llh-" + x + "-" + y + "'></td>";
}
this.gameMapData += "</tr>";
}
this.buttonPrompt = "地图渲染完成(开始游戏)"; // 改变按钮文字
this.buttonColorNum = 0; // 改变按钮颜色
this.speedMirroring = this.speed; // 将速度镜像赋值
/* 为了展示手机端的上下左右按钮,PC不展示 */
this.butWASD = !this.isPC() // 赋值是否为PC
}
})
</script>
</html>
更多推荐
已为社区贡献1条内容
所有评论(0)