看了超哥的课后总结贪吃蛇的布局及实现。
大部分代码标注了注释,欢迎大家一起探讨。
一、思路分析:
1、移动时:
首先判断用户的按键是否为你规定的上下左右;
根据当前蛇头位置的x,y的位置,得到将要移动到的x,y的位置;
蛇的每一次移动是将蛇尾放到将要移动到的x,y位置上,而不是移动所有的div;蛇不能掉头,通过在每一次的定时器内只能进行一次更改方向实现。
2、吃食物后:
判断蛇头是否和随机生成的食物的x,y位置相同,相同则视为吃到食物;
蛇需要生成一个新的div;
食物需要再次随机一个x,y并移动;
加分数,判断是否加等级。
3、游戏结束:
蛇不能撞到四边的边框;
蛇不能撞到自己,遍历整个蛇的div,判断蛇头下次移动的x,y是否和当前的div重合;注意:不需要判断第一个和最后一个div,因为不会碰到。
二、H5部分:
<div id="main">
<div id="stage">
<div id="snake">
<div></div>
</div>
<div id="food">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div id="info">
<div>SCORE:<span id="score">0</span></div>
<div>LEVEL:<span id="level">1</span></div>
</div>
</div>
三、CSS样式:
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#main {
height: 420px;
width: 360px;
border: 10px #000 solid;
background-color: #b7d4a8;
border-radius: 20px;
margin: 50px auto;
}
#stage {
width: 304px;
height: 304px;
border: 2px solid #000;
margin: 20px auto;
position: relative;
}
#snake>div {
width: 10px;
height: 10px;
background-color: #000;
position: absolute;
border: 1px solid #b7d4a8;
}
#food {
width: 10px;
height: 10px;
position: absolute;
top: 100px;
left: 120px;
display: flex;
flex-flow: wrap;
}
#food>div {
width: 5px;
height: 5px;
background-color: #000;
transform: rotate(45deg);
}
#info {
width: 304px;
margin: 0px auto;
display: flex;
justify-content: space-between;
font: bold 20px courier;
}
</style>
四、JS代码:
<script>
const scoreSpan = document.getElementById("score");
const levelSpan = document.getElementById("level");
const snake = document.getElementById("snake");
const snakes = snake.getElementsByTagName("div");
//存放上下左右按键
const keyArr = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
//根据reObj判断蛇掉头
const reObj = {
ArrowUp: "ArrowDown",
ArrowDown: "ArrowUp",
ArrowLeft: "ArrowRight",
ArrowRight: "ArrowLeft"
}
const food = document.getElementById("food")
//定义更改方向
let dir;
//在一次定时器内只能改变一次方向开关
let keyActive = true;
let score = 0;
let level = 0;
//键盘事件
document.addEventListener("keydown", (event) => {
if (keyActive && keyArr.indexOf(event.key) !== -1) {
if (snakes.length < 2 || reObj[dir] !== event.key) {
dir = event.key;
keyActive = false;
}
}
})
//根据边框大小,随机生成食物坐标
function changeFood() {
//食物的坐标应该在x:0-290 y:0-290
const x = Math.floor(Math.random() * 30) * 10
const y = Math.floor(Math.random() * 30) * 10
//设置食物坐标
food.style.left = x + "px";
food.style.top = y + "px";
}
changeFood();
//定时器获取蛇的位置
setTimeout(function move() {
keyActive = true;
const snakeHead = snakes[0];
//获取当前蛇头的x,y坐标
let x = snakeHead.offsetLeft
let y = snakeHead.offsetTop
//根据按键修改x,y坐标
switch (dir) {
case "ArrowUp":
y -= 10
break;
case "ArrowDown":
y += 10
break;
case "ArrowLeft":
x -= 10
break;
case "ArrowRight":
x += 10
break;
}
//判断游戏是否结束
//判断是否撞墙
if (x < 0 || x > 290 || y < 0 || y > 290) {
alert("游戏结束")
return;
}
//判断是否撞到自己
for (let i = 1; i < snakes.length - 1; i++) {
if (snakes[i].offsetLeft === x && snakes[i].offsetTop === y) {
alert("游戏结束")
return;
}
}
//检查蛇是否吃到食物
if (snakeHead.offsetTop === food.offsetTop && snakeHead.offsetLeft === food.offsetLeft) {
changeFood();
const div = document.createElement("div")
snake.appendChild(div);
//加分
score++;
scoreSpan.textContent = score;
//加等级
if (score % 6 === 0 && level < 14) {
level++;
levelSpan.textContent = level + 1;
}
}
//获取蛇的尾巴
const snakeTail = snakes[snakes.length - 1]
//移动蛇的位置
snakeTail.style.left = x + "px"
snakeTail.style.top = y + "px"
//将蛇头的位置换成蛇尾
snake.insertAdjacentElement("afterbegin", snakeTail)
setTimeout(move, 300 - (level * 20))
}, 300)
</script>