首页 > 编程语言 >javascript - 练习题:事件练习 - 贪吃蛇

javascript - 练习题:事件练习 - 贪吃蛇

时间:2022-11-20 23:40:09浏览次数:39  
标签:练习题 style food javascript 贪吃蛇 snake snakePos var domContent

贪吃蛇

原生JS(非面向对象的方式),渡一教学的笔记;

javascript - 练习题:事件练习 - 贪吃蛇_事件练习

地图坐标

{0,0}

{1,0}

{2,0}

{3,0}

{4,0}

{0,1}

{1,1}

{2,1}

{3,1}

{4,1}

{0,2}

{1,2}

{2,2}

{3,2}

{4,2}

{0,3}

{1,3}

{2,3}

{3,3}

{4,3}

{0,4}

{1,4}

{2,4}

{3,4}

{4,4}

共三个文件,分别是:index.html,index.js,config.js

和四个图片文件:放在博文最后;

javascript - 练习题:事件练习 - 贪吃蛇_贪吃蛇_02


index.html

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>贪吃蛇</title>
<style>
* {
margin: 0;
padding: 0;
}

.container {
width: 600px;
height: 600px;
background: #225675;
border: 20px solid #7dd9ff;
margin: 20px auto 0;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}

.container button {
border: none;
outline: none;
}

.startBtn {
width: 200px;
height: 80px;
background: url(./imgs/startGame.png) center / contain no-repeat;
display: block;
}

.pauseBtn {
width: 70px;
height: 70px;
background: url(./imgs/start.png) center / contain no-repeat;
display: none;
}
</style>
</head>

<body>
<div class="container">
<!-- 开始游戏按钮 -->
<button class="startBtn"></button>
<!-- 暂停游戏按钮 -->
<button class="pauseBtn"></button>
</div>

<script src="config.js"></script>
<script src="index.js"></script>
</body>

</html>

index.js

/**
* 绘制蛇的方法
* @param{*} snake
*/
function drawSnake(snake) {
for (var i = 0; i < snake.snakePos.length; i++) {
if (!snake.snakePos[i].domContent) {
// 如果进入此 if , 说明是第一次创建蛇;
snake.snakePos[i].domContent = document.createElement('div');
snake.snakePos[i].domContent.style.position = 'absolute';
snake.snakePos[i].domContent.style.width = snakeBody + 'px';
snake.snakePos[i].domContent.style.height = snakeBody + 'px';
snake.snakePos[i].domContent.style.left = snake.snakePos[i].x * snakeBody + 'px';
snake.snakePos[i].domContent.style.top = snake.snakePos[i].y * snakeBody + 'px';
if (snake.snakePos[i].flag === 'head') {
// 说明是蛇头
snake.snakePos[i].domContent.style.background = `url("./imgs/snake.png") center / contain no-repeat`;
// 根据方向进行旋转
switch (snake.direction.flag) {
case 'top': {
snake.snakePos[i].domContent.style.transform = `rotate(-90deg)`;
break;
}
case 'bottom': {
snake.snakePos[i].domContent.style.transform = `rotate(90deg)`;
break;
}
case 'left': {
snake.snakePos[i].domContent.style.transform = `rotate(180deg)`;
break;
}
case 'right': {
snake.snakePos[i].domContent.style.transform = `rotate(0deg)`;
break;
}
};
} else {
// 说明是蛇身
snake.snakePos[i].domContent.style.background = "#9ddbb1";
snake.snakePos[i].domContent.style.borderRadius = "50%";

}
}
// 需要把创建的DOM元素添加到 container 容器上面
document.querySelector(".container").append(snake.snakePos[i].domContent);
}
}

/**
* 绘制食物的方法
*/
function drawFood() {
// 1. 食物的坐标是随机的
// 2. 食物不能生成在画板外面,也不能生成在蛇身上
while (true) {
// 构成一个死循环,直到生成符合要求的食物坐标才能退出循环
var isRepeat = false; // 默认生成的坐标是符合要求的
food.x = Math.floor(Math.random() * tr);
food.y = Math.floor(Math.random() * tr);
// 查看坐标是否符合要求
for (var i = 0; i < snake.snakePos.length; i++) {
if (snake.snakePos[i].x === food.x && snake.snakePos[i].y === food.y) {
// 进入此if 说明当前生成的食物坐标和蛇的坐标冲突
isRepeat = true;
break;
}
}
if (!isRepeat) {
// 跳出 while 循环
break;
}
}
// 整个while循环跳出来之后,食物的坐标一定是OK的;
if (!food.domContent) {
food.domContent = document.createElement('div');
food.domContent.style.width = snakeBody + 'px';
food.domContent.style.height = snakeBody + 'px';
food.domContent.style.position = 'absolute';
food.domContent.style.background = `url("./imgs/food.png") center / contain no-repeat`;
document.querySelector('.container').append(food.domContent);
}
food.domContent.style.left = food.x * snakeBody + 'px';
food.domContent.style.top = food.y * snakeBody + 'px';
}

/**
* 蛇的移动方法
*/
function snakeMove() {
var oldHead = snake.snakePos[snake.snakePos.length - 1];
// 根据方向,计算出新的蛇头坐标
var newHead = {
domContent: "",
x: oldHead.x + snake.direction.x,
y: oldHead.y + snake.direction.y,
flag: 'head'
}
// 做碰撞检测,看计算出来的蛇头有没有碰上食物、身体或墙壁
var collideCheckResult = isCollide(newHead);
console.log(collideCheckResult);
if (collideCheckResult.isCollide) {
// 进入此 if 说明,碰墙了;
if (window.confirm(`游戏结束,当前得分${score}分,是否重新开始游戏?`)) {
// 重新开始游戏
document.querySelector('.container').innerHTML = `
<button class="startBtn" style= "display:none;"></button>
<button class="pauseBtn" style= "display:none;"></button>
`;
score = 0;
snake = {
direction: directionNum.right,
snakePos: [
{ x: 0, y: 0, domContent: "", flag: 'body' },
{ x: 1, y: 0, domContent: "", flag: 'body' },
{ x: 2, y: 0, domContent: "", flag: 'body' },
{ x: 3, y: 0, domContent: "", flag: 'head' },
]
}
food = {
x: 0, y: 0, domContent: ""
}
initGame();
} else {
// 结束游戏
document.onkeydown = null;
clearInterval(timerStop);
}
return;

}

// 将旧的头修改为身体
oldHead.flag = 'body';
oldHead.domContent.style.background = "#9ddbb1";
oldHead.domContent.style.borderRadius = "50%";
snake.snakePos.push(newHead);

// 判断是否吃到东西
if (collideCheckResult.isEat) {
// 重新生成食物
drawFood();
} else {
// 说明没有吃到食物,移除最后一个元素
document.querySelector('.container').removeChild(snake.snakePos[0].domContent);
snake.snakePos.shift();
}
// 重新绘制蛇
drawSnake(snake);

}

/**
* 碰撞检测
* @param {*} newHead 新计算出来的蛇头坐标
*/
function isCollide(newHead) {
var collideCheckInfo = {
isCollide: false, // 是否碰撞墙壁,蛇身;
isEat: false // 是否吃到食物
}
// 1. 检测是否碰到墙壁
if (newHead.x < 0 || newHead.x >= td || newHead.y < 0 || newHead.y >= tr) {
collideCheckInfo.isCollide = true;
return collideCheckInfo;
}
// 2. 检测是否碰到自己
for (var i = 0; i < snake.snakePos.length; i++) {
if (snake.snakePos[i].x === newHead.x && snake.snakePos[i].y === newHead.y) {
collideCheckInfo.isCollide = true;
return collideCheckInfo;
}
}
// 3. 检测是否吃到食物
if (newHead.x === food.x && newHead.y === food.y) {
collideCheckInfo.isEat = true;
score++;
}
return collideCheckInfo;
}

function startGame() {
timerStop = setInterval(() => {
snakeMove();
}, time);
}
/**
* 绑定事件
*/

function bindEvent() {
// 1. 首先是键盘事件,用户按上下左右,蛇能够移动
document.onkeydown = function (e) {
// console.log(e.key);
if ((e.key === "ArrowUp" || e.key.toLocaleLowerCase() === 'w') && snake.direction.flag !== 'bottom') {
// 用户按的是上
snake.direction = directionNum.top;
}
if ((e.key === "ArrowDown" || e.key.toLocaleLowerCase() === 's') && snake.direction.flag !== 'top') {
// 用户按的是下
snake.direction = directionNum.bottom;
}
if ((e.key === "ArrowLeft" || e.key.toLocaleLowerCase() === 'a') && snake.direction.flag !== 'right') {
// 用户按的是左
snake.direction = directionNum.left;
}
if ((e.key === "ArrowRight" || e.key.toLocaleLowerCase() === 'd') && snake.direction.flag !== 'left') {
// 用户按的是右
snake.direction = directionNum.right;
}
// console.log(snake.direction);
snakeMove();
}
// 2. 计时器自动调用蛇移动的方法
startGame();
// 3. 点击整个容器的时候,可以暂停和重新开始游戏
document.querySelector('.container').onclick = function (e) {
// 通过事件委托的形式,判断用户点击的 container 还是 pause,从而做相应处理
if (e.target.className === '.container') {
// 要做暂停操作
document.querySelector('.pauseBtn').style.display = 'block';
clearInterval(timerStop);
} else {
// 恢复游戏操作
document.querySelector('.pauseBtn').style.display = 'none';
startGame();
}
}
}


/**
* 游戏初始化
*/

function initGame() {
// 1. 初始化地图
for (var i = 0; i < tr; i++) {
for (var j = 0; j < td; j++) {
gridData.push({
x: j,
y: i
});
}
}
// console.log(gridData);

// 2. 绘制蛇
drawSnake(snake);

// 3. 绘制食物
drawFood();
}

/**
* 游戏主方法
*/
function main() {
// 等待用户点击开始
document.querySelector('.startBtn').onclick = function (e) {
e.stopPropagation();
document.querySelector('.startBtn').style.display = 'none';
// 1. 初始化游戏
initGame();
// 2. 绑定事件
bindEvent();
}
}
main();

config.js

// 游戏相关配置

var gridData = [];

// 整个网格的行与列
var tr = 30;
var td = 30;

// 蛇的身体大小
var snakeBody = 20;

// 明确新的蛇头和旧的蛇头的位置
// 我们在确定新的蛇头坐标的时候,会拿下面的对象和旧蛇头做个计算,得出新蛇头坐标
var directionNum = {
left: { x: -1, y: 0, flag: 'left' },
right: { x: 1, y: 0, flag: 'right' },
top: { x: 0, y: -1, flag: 'top' },
bottom: { x: 0, y: 1, flag: 'bottom' },
}

// 蛇相关的配置信息
var snake = {
// 蛇一开始移动的方向
direction: directionNum.right, // 一开始向右移动
// 蛇的初始位置
snakePos: [
{ x: 0, y: 0, domContent: "", flag: 'body' },
{ x: 1, y: 0, domContent: "", flag: 'body' },
{ x: 2, y: 0, domContent: "", flag: 'body' },
{ x: 3, y: 0, domContent: "", flag: 'head' },
],
};

// 食物相关的配置信息
var food = {
x: 0, y: 0, domContent: ""
}

// 游戏分数
var score = 0;

// 停止计时器
var timerStop = null;

// 计时器时间
var time = 500;


图片可以随便找个类型的;

food.png

javascript - 练习题:事件练习 - 贪吃蛇_javascript_03

snake.png

javascript - 练习题:事件练习 - 贪吃蛇_javascript_04

start.png

javascript - 练习题:事件练习 - 贪吃蛇_javascript_05

startGame.png

javascript - 练习题:事件练习 - 贪吃蛇_事件练习_06

标签:练习题,style,food,javascript,贪吃蛇,snake,snakePos,var,domContent
From: https://blog.51cto.com/ahuiok/5872143

相关文章