<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>贪吃蛇</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<div id="map"></div>
<script src="../js/tool.js"></script>
<script src="../js/food.js"></script>
<script src="../js/snake.js"></script>
<script src="../js/game.js"></script>
</body>
</html>
//随机数生成
let Tools = {
getRandom: function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
},
};
//***************************面向对象编程 赞👍*********************************\\
//解决命名冲突 -自调用函数(开启一个新的作用域)
(function () {//局部作用域
let position = 'absolute';
//存储food,方便删除
let elements = [];
function Food(options) {
//options是一个对象如果没传参就是{}
options = options || {};//如果没有传参则指向||后面的值
//options = 传入的对象 或者 {}
this.x = options.x || 0;
this.y = options.y || 0;
this.width = options.width || 20;
this.height = options.height || 20;
this.color = options.color || 'green';
}
//渲染
Food.prototype.render = function (map) {
//删除之前创建的food
remove();
//随机设置x和y的值
this.x = Tools.getRandom(0, (map.offsetWidth / this.width - 1) * this.width);
this.y = Tools.getRandom(0, (map.offsetHeight / this.height - 1) * this.height);
console.log(this.x);
console.log(this.y);
//动态创建div,页面上显示的食物
let div = document.createElement('div');
map.appendChild(div);
//将创建的div放到数组中
elements.push(div);
//设置div样式
// div.className = 'food';//也可以直接添加一个定义好的样式,但变化没有下面变量存储灵活
div.style.position = position;//可以根据需求改动变量
div.style.left = this.x + 'px';
div.style.top = this.y + 'px';
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.background = this.color;
console.log('👍');
};
function remove() {
for (let i = elements.length - 1; i >= 0; i--) {
//删除div
elements[i].parentNode.removeChild(elements[i]);
//清空数组
//splice()两个参数 1,从哪删 2,删几个
elements.splice(i, 1);
}
}
//因为这里是局部作用域,所以外部无法访问这里定义的变量,
// 要把Food构造函数,让外部可以访问 ,将它添加到window中
window.Food = Food;
})();
// let option = {
// x:random(0,750)+'px',
// y:random(0,550)+'px',
// width:50,
// height:50,
// color:'pink'
// };
//测试test
//let map = document.querySelector('#map');
//let food = new Food();//不添加参数就是 || 后面设置的值
//food.render(map);//调用Food的render方法(实际是Food类的一个属性prototype)给div设置样式和添加div美其名曰:渲染
(function () {
let position = 'absolute';
let elements = [];//每一个蛇
function Snake(options) {
options = options || {};
//蛇节的大小
this.width = options.width || 20;
this.height = options.height || 20;
//蛇节的移动方向
this.direction = options.direction || 'right';
//蛇的身体(蛇节)的第一个元素是蛇头
this.body = [
{x: 2, y: 2, color: 'red'},
{x: 1, y: 2, color: 'blue'},
{x: 0, y: 2, color: 'blue'}
];
}
Snake.prototype.render = function (map) {
//删除以前创建的蛇
remove();
//把每一个蛇节渲染到map上
for (let i = 0; i < this.body.length; i++) {
//蛇节
let object = this.body[i];
let div = document.createElement('div');
map.appendChild(div);
//记录当前创建的蛇
elements.push(div);
//设置样式
div.style.position = position;
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.left = object.x * this.width + 'px';
div.style.top = object.y * this.height + 'px';
div.style.background = object.color;
}
};
function remove () {
for (let i = elements.length - 1;i>=0;i--){
//删除div
elements[i].parentNode.removeChild(elements[i]);
//删除数组中的元素
elements.splice(i,1);
}
}
//蛇移动方法
Snake.prototype.move = function (food,map) {
//1,蛇的身体移动(当前蛇节到上一个蛇节的位置)
for (let i = this.body.length-1; i > 0; i--) {
this.body[i].x = this.body[i - 1].x;
this.body[i].y = this.body[i - 1].y;
}
//2,控制蛇移动的方向
// 控制蛇头的移动
let head = this.body[0];
switch (this.direction) {
case 'right':
head.x += 1;
break;
case 'top':
head.y -= 1;
break;
case 'left':
head.x -= 1;
break;
case "bottom":
head.y += 1;
break;
default:
console.log("default");
}
//遇到food
let headX = head.x * this.width;
let headY = head.y * this.height;
if (headX === food.x && headY === food.y){
//蛇身长一节
let last = this.body[this.body.length - 1];
this.body.push({
x:last.x,
y:last.y,
color:last.color
});
//随机生成food
food.render(map);
}
};
//把Snake暴露出去
window.Snake = Snake;
})();
//test
//let snake = new window.Snake();
//snake.render(map);
(function () {
var that;
function Game(map) {
that = this;
this.food = new Food();
this.snake = new Snake();
this.map = map;
}
Game.prototype.start = function () {
// 1,把food和snake渲染到map上
this.food.render(this.map);
this.snake.render(this.map);
//测试 Snake.move方法
// this.snake.move();
// this.snake.render(this.map);
// this.snake.move();
// this.snake.render(this.map);
// this.snake.move();
// this.snake.render(this.map);
//2,开始游戏的逻辑
// 2.1,让蛇动起来
function runSnake() {
let timerId = setInterval(function () {
that.snake.move(that.food,that.map);
that.snake.render(that.map);
//2.2 遇到边界
//获取蛇头的坐标
let maxX = that.map.offsetWidth / that.snake.width;
let maxY = that.map.offsetHeight / that.snake.height;
let headX = that.snake.body[0].x;
let headY = that.snake.body[0].y;
if (headX < 0 || headX >= maxX){
alert('Game over!');
clearInterval(timerId);
}
if (headY <0 ||headY >= maxY){
alert('Game over!');
clearInterval(timerId);
}
},150);
}
runSnake();
//2.2,键盘控制移动方向
function bindKey() {
// document.onkeydown = function () {};//鼠标事件的两种添加方式
/*
* 37 left
* 38 top
* 39 right
* 40 bottom
* */
document.addEventListener('keydown',function (e) {
switch (e.keyCode) {
case 37:
that.snake.direction = 'left';
break;
case 38:
that.snake.direction = 'top';
break;
case 39:
that.snake.direction = 'right';
break;
case 40:
that.snake.direction = 'bottom';
break;
}
},false);
}
bindKey();
//2.3,遇到food
};
//暴露构造函数给外部
window.Game = Game;
})();
//test
let map = document.querySelector('#map');
let game = new Game(map);
game.start();