【前端三剑客】简单前端小游戏贪吃蛇

游戏界面【前端三剑客】简单前端小游戏贪吃蛇_第1张图片

思路

  • 用table画地图
  • 每个td给一个id当做坐标,格式(x_y)
  • 怎么区分食物、蛇与空白区域(行动的区域)?
    • 食物添加类(.food)
    • 蛇身体添加类(.black)
    • 空白区域添加类(.white)
  • 怎么让蛇移动?
    • 给蛇对象添加一个默认行进方向
    • setInterval设置定时器
    • 每隔一段时间让蛇朝着该方向移动
    • 蛇对象存储坐标数组,目的为了更方便控制蛇的移动(使用id找到蛇的身体)
    • 坐标数组整体后移一位(插入新的蛇头坐标),再删除原蛇尾坐标
  • 怎么判断蛇的碰撞与吃到自己身体?
    • 根据td的类来判断
  • 吃到食物怎么办?
    • 吃到食物改变逻辑,移动后不删除蛇尾

index.html


<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js">script>
    <link rel="stylesheet" href="game.css">
    <title>贪吃蛇title>
head>
<body>
    <p id="score">得分:<span id="score_number">0span>p>
    <table cellpadding="0" cellspacing="0" id="playground">table>
    
    <script src="game.js">script>
body>
html>

game.css

#playground{
    border-collapse: collapse;
    margin: auto;
}
#playground td{
    width: 15px;
    height: 15px;
    border: 1px solid gainsboro;
}

#score_number{
    color: tomato;
    font-size: larger;
}
.black{
    background: black;
}

.white{
    background: white;
}

.food{
	background: greenyellow;
}

game.js

// 地图宽
var map_width = 30;
// 游戏定时器
var timer;
// 蛇对象
var snake;

function setClass(id, cn) {
	$(id).removeClass();
	$(id).addClass(cn);
}

// 产生食物
function createFood() {
	let x, y;
	let idName;
	do {
		x = Math.floor(Math.random() * map_width);
		y = Math.floor(Math.random() * map_width);
		idName = '#' + x + '_' + y;
	} while ($(idName).hasClass('black'));
	setClass(idName, 'food');
}
// 创建蛇对象
function Snake() {
	// 初始长度3
	this.snakeBody = [
		[1, 3],
		[1, 2],
		[1, 1]
	];
	// 初始方向
	this.direction = "right";

	// 初始化小蛇
	for (let i = 0; i < this.snakeBody.length; ++i) {
		let x = this.snakeBody[i][0];
		let y = this.snakeBody[i][1];
		let idName = '#' + x + '_' + y;
		$(idName).removeClass();
		$(idName).addClass('black');
	}

	this.autoMove = function() {
		function move() {
			let x = snake.snakeBody[0][0];
			let y = snake.snakeBody[0][1];

			switch (snake.direction) {
				case 'up':
					x -= 1;
					break;
				case 'down':
					x += 1;
					break;
				case 'left':
					y -= 1;
					break;
				case 'right':
					y += 1;
					break;
			}
			let idName = "#" + x + "_" + y;
			// 判断撞墙或者吃到自己身体
			if (x < 0 || x >= map_width || y < 0 || y >= map_width || $(idName).hasClass('black')) {
				alert("游戏结束");
				clearInterval(timer);
				return;
			}
			// 蛇身前移
			snake.snakeBody.unshift([x, y]);
			// 吃到食物
			if ($(idName).hasClass('food')) {
				$(idName).removeClass('food');
				// 更新分数
				let score = parseInt($("#score_number").text()) + 10;
				$("#score_number").text(score);
				// 0.5秒后出现新的食物
				setTimeout(createFood, 0.5);
			} else {
				// 没吃到食物删除尾巴
				let p = snake.snakeBody.pop();
				let popIdName = '#' + p[0] + '_' + p[1];
				setClass(popIdName, 'white');
			}
			// 新位置为蛇身
			setClass(idName, 'black');
		}
		// 200ms移动一次
		timer = setInterval(move, 200);
	}
}

// 网页加载时执行
window.onload = function() {
	// 创建地图
	for (let i = 0; i < this.map_width; ++i) {
		let tr = document.createElement("tr");
		for (let j = 0; j < this.map_width; ++j) {
			let td = document.createElement('td');
			td.setAttribute("class", "white");
			td.setAttribute('id', i + '_' + j);
			tr.appendChild(td);
		}
		$("#playground").append(tr);
	}

	// 1秒后创造第一个食物
	setTimeout(createFood, 1000);
	// 创造蛇对象
	snake = new Snake();
	snake.autoMove();

	// 全局按键事件
	$(document).keydown(function(event) {
		switch (event.keyCode) {
			case 37:
				if (snake.direction != 'right') {
					snake.direction = "left";
				}
				break;
			case 39:
				if (snake.direction != 'left') {
					snake.direction = "right";
				}
				break;
			case 38:
				if (snake.direction != 'down') {
					snake.direction = "up";
				}
				break;
			case 40:
				if (snake.direction != 'up') {
					snake.direction = "down";
				}
				break;
			case 32:
				// 空格暂停
				if (timer != null) {
					clearInterval(timer);
					timer = null;
				} else {
					snake.autoMove();
				}
		}
		console.log("蛇(" + snake.snakeBody[0][0] + "," + snake.snakeBody[0][1] + ")的方向: " + snake.direction);
	});
}




BUG

在定时器还未调用move期间按下了多个方向键(该代码期间是200ms),蛇的坐标为更新,当更新时,蛇对象里的默认方向指向了自己的蛇身(蛇头下一个位置,对应坐标数组snake.snakeBody[1]),导致蛇头吃到自己蛇身,从而游戏结束!

你可能感兴趣的:(前端三剑客)