前言
面向对象实现贪吃蛇
1.封装食物对象
代码如下(示例):
(function (window) {
"use strict"
function Food(options) {
options = options || {}
this.width = options.width || 20;
this.height = options.height || 20;
this.bgc = options.bgc || "#409eff";
this.x = options.x || 0;
this.y = options.y || 0;
}
Food.prototype = {
render: function (target) {
const foodDiv = document.createElement("div");
foodDiv.style.width = this.width + 'px';
foodDiv.style.height = this.height + 'px';
foodDiv.style.background = this.bgc;
this.x = parseInt(Math.random() * (target.offsetWidth / this.width));//offsetWidth 元素真实的宽度
this.y = parseInt(Math.random() * (target.offsetHeight / this.height));
foodDiv.style.position = 'absolute';
foodDiv.style.left = this.x * this.width + 'px';
foodDiv.style.top = this.y * this.height + 'px';
target.appendChild(foodDiv);//appendChild 添加结点到父元素的最后面
}
}
window.Food = Food;
})(window)
2.封装蛇对象
代码如下(示例):
(function (window) {
"use strict"
function Snake(options) {
options = options || {};
this.width = options.width || 20;
this.height = options.height || 20;
this.headBgc = options.headBgc || "mediumturquoise";
this.bodyBgc = options.bodyBgc || "lightgreen";
this.direction = options.direction || "right";
this.body = options.body || [
{ x: 2, y: 0 },
{ x: 1, y: 0 },
{ x: 0, y: 0 }
]
}
Snake.prototype = {
render: function (target) {
for (var i = 0; i < this.body.length; i++) {
var span = document.createElement("span");
span.style.width = this.width + 'px';
span.style.height = this.height + 'px';
if (i === 0) {
span.style.background = this.headBgc;
} else {
span.style.background = this.bodyBgc;
}
span.style.position = 'absolute';
span.style.left = this.width * this.body[i].x + 'px';
span.style.top = this.height * this.body[i].y + 'px';
target.appendChild(span);
}
},
// 蛇移动 复制蛇头,删除蛇尾
move: function (target, food, grade) {
const newHead = {
x: this.body[0].x,
y: this.body[0].y
}
this.body.unshift(newHead);
switch (this.direction) {
case "top":
newHead.y--;
break;
case "right":
newHead.x++;
break;
case "bottom":
newHead.y++;
break;
case "left":
newHead.x--;
break;
default:
break;
}
/** 判断蛇有没有吃到食物
* head的坐标是否与食物的坐标相等
* 若吃到食物,则不删除身体最后一节
**/
var head = this.body[0];
if (head.x === food.x && head.y === food.y) {
// 计分
grade += 10;
const scoreSpan = document.querySelector("#score");
scoreSpan.innerHTML = grade;
var div = target.querySelector("div");
target.removeChild(div);
food.render(target);
} else {
this.body.pop();
}
// 删除地图上已有的蛇,然后再重新渲染
const spans = target.querySelectorAll("span")//querySelectorAll()获取到的是一个伪数组
for (let i = 0; i < spans.length; i++) {
target.removeChild(spans[i]);//removeChild 一次只能删除一个标签
}
this.render(target);
return grade;
}
}
window.Snake = Snake;
})(window)
3.封装游戏对象
代码如下(示例):
(function (window) {
"use strict"
function Game(target) {
this.food = new Food();
this.snake = new Snake();
this.map = target;
this.score = 0;
}
Game.prototype = {
render: function () {
this.food.render(this.map);
this.snake.render(this.map);
const scoreSpan = document.querySelector("#score");
scoreSpan.innerHTML = this.score;
},
startGame: function () {
var that = this;
var timeId = setInterval(function () {
// 定时器中的this指向document
that.score = that.snake.move(that.map, that.food, that.score);
// 判断蛇头是否撞墙
const head = that.snake.body[0];
if (head.x < 0 ||
head.x >= that.map.offsetWidth / that.snake.width ||
head.y < 0 ||
head.y >= that.map.offsetHeight / that.snake.height
) {
alert("Game Over");
clearInterval(timeId);
}
/**判断蛇是否吃到自己
* 遍历蛇头与自己身体的坐标是否重合
*/
for (let i = 4; i < that.snake.body.length; i++) {
if (head.x == that.snake.body[i].x && head.y == that.snake.body[i].y) {
alert("Game Over");
clearInterval(timeId);
}
}
}, 100);
/** 控制蛇的移动
* 1.给页面添加keyup事件
* 2.获取key
* 3.通过key改变蛇的direction属性
*/
document.onkeyup = function (e) {
var keyCode = e.keyCode;
if (keyCode === 37) {
if (that.snake.direction === "right") {
return;
}
that.snake.direction = "left";
} else if (keyCode === 38) {
if (that.snake.direction === "bottom") {
return;
}
that.snake.direction = "top"
} else if (keyCode === 39) {
if (that.snake.direction === "left") {
return;
}
that.snake.direction = "right"
} else if (keyCode === 40) {
if (that.snake.direction === "top") {
return;
}
that.snake.direction = "bottom"
}
}
}
}
// 暴露的方法添加在window上,一个js只暴露一个核心功能
window.Game = Game;
})(window)
4.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">
<title>Document</title>
<style>
#map {
height: 800px;
width: 1200px;
background: #ddd;
margin: 10px auto 20px auto;
position: relative;
}
input[type="button"] {
background: #409eff;
color: #fff;
border: none;
height: 40px;
padding: 0 16px;
display: block;
/*块级元素独占一行*/
margin: 10px auto;
border-radius: 2px;
}
input[type="button"]:hover {
background: rgb(121, 188, 255);
}
input[type="button"]:focus {
border:none;
}
input[type="button"]:active {
background: #2a8ef1;
}
.total{
font-size:24px;
color: #303030;
width: 1200px;
margin:20px auto 0px auto;
}
.total #score{
color:rgb(41, 241, 225);
}
</style>
</head>
<body>
<div class="total">分数:<span id="score"></span></div>
<div id="map"></div>
<input type="button" value="开始游戏" />
<script src="./food.js"></script>
<script src="./snake.js"></script>
<script src="./game.js"></script>
<script>
const map = document.querySelector("#map");
const btn = document.querySelector("input");
const game = new Game(map);
game.render();
btn.onclick = function(){
game.startGame();
}
</script>
</body>
</html>