思路:不论我们用什么方法做东西,首先就是看到一个项目时的思路。做贪吃蛇这个游戏,就是把它分割成四个对象,一个食物对象,一个小蛇对象,一个地图对象,同时游戏本身也可以看做一个对象。
接下来书写我们的代码,首先是html和css 地图在这里我们直接用css搞定,不需要单独处理
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
#map{
width: 800px;
height: 600px;
background-color: #ccc;
position: relative;
}
#map div{
position: absolute;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="food.js"></script>
<script src="snake.js"></script>
<script src="game.js"></script>
</body>
</html>
分析食物对象,食物有宽,高,背景色,和坐标(并且这个坐标是随机的)
(function(){
//创建一个食物的构造函数
function Food(options){
//设置食物的宽高背景颜色
this.width = options.width || 20;
this.height = options.height || 20;
this.bgColor = options.bgColor || "green";
//设置食物的初始坐标
this.x = 0;
this.y = 0;
//为了功能扩展,把地图也设置为一个属性
this.map = options.map;
this.element;
}
//初始化食物的方法-----给食物的原型对象添加
Food.prototype.init = function () {
//在创建新食物之前删除旧食物
if(this.element){
this.map.removeChild(this.element);
}
//创建一个食物
var div = document.createElement('div');
//把创建食物保存到element中
this.element = div;
//设置食物的宽高背景颜色
div.style.width = this.width + "px";
div.style.height = this.height + "px";
div.style.backgroundColor = this.bgColor;
//食物的坐标
var maxWidthCount = Math.floor(this.map.offsetWidth / this.width);
var maxHeightCount = Math.floor(this.map.offsetHeight / this.height);
this.x = Math.floor(Math.random() * maxWidthCount);
this.y = Math.floor(Math.random() * maxHeightCount);
div.style.left = this.x * this.width + "px";
div.style.top = this.y * this.height + "px";
//把食物追加到地图上显示
this.map.appendChild(div);
}
window.Food = Food;
})();
分析小蛇,小蛇也是有宽高背景色,不过在这里要注意的是蛇身体是由多个盒子组成的,所以要用数组的形式来表示
//小蛇对象
(function(){
//创建小蛇的构造函数
function Snake (options){
//设置小蛇的属性 宽高
this.width = options.width ||20;
this.height = options.height ||20;
//由于蛇身有三个盒子组成,所以用数组来表示
this.body = [
{x:1,y:1,bgColor:"orange"},
{x:2,y:1,bgColor:"orange"},
{x:3,y:1,bgColor:"red"}
];
this.map =options.map;
//数组用于存放蛇身体,便于删除
this.elements =[];
//控制小蛇方向的属性
this.direction = "right";
}
//通过原型对象的方法初始化小蛇---画小蛇
Snake.prototype.init = function(){
//删除之前的小蛇(要删除地图上的小蛇,也要删除数组中的小蛇)
//删除地图上的小蛇
for(var i=this.elements.length-1;i>=0;i--){
this.map.removeChild(this.elements[i]);
}
//删除数组中的小蛇
this.elements = [];
//console.log(this.elements);
//用循环创建小蛇的身体
for(var i=0;i<this.body.length;i++){
//创建一个盒子
var div = document.createElement('div');
//设置属性
div.style.width = this.width + "px";
div.style.height = this.height + "px";
div.style.backgroundColor = this.body[i].bgColor;
div.style.left = this.body[i].x * this.width + "px";
div.style.top = this.body[i].y * this.height + "px";
//追加到地图上显示
this.map.appendChild(div);
//把小蛇的身体存入数组中
this.elements.push(div);
}
};
//小蛇移动
Snake.prototype.move = function(){
//循环蛇身体,改变蛇身体的坐标
for(var i=0;i<this.body.length-1;i++){
this.body[i].x = this.body[i+1].x;
this.body[i].y = this.body[i+1].y;
}
//蛇头单独来改变
switch (this.direction){
case "left":
this.body[this.body.length-1].x--;
break;
case "up":
this.body[this.body.length-1].y--;
break;
case "right":
this.body[this.body.length-1].x++;
break;
case "down":
this.body[this.body.length-1].y++;
break;
}
//当坐标改变后重新画小蛇
//为了游戏结束的效果好看,移动到Game的检测后执行
//this.init();
};
//暴露给全局
window.Snake = Snake;
})();
最后是游戏对象
//游戏控制对象
(function () {
function Game(options){
//设置属性:食物,小蛇,地图
this.food = options.food;
this.snake = options.snake;
this.map = options.map;
}
Game.prototype.init = function(){
//绘制小蛇
this.snake.init();
//绘制食物
this.food.init();
//让小蛇运动
this.runSnake();
//设置一个功能,用于按键控制小蛇运动
this.changeDirection();
}
//小蛇运动
Game.prototype.runSnake = function(){
//因为定时器里的this默认指向window,所以在定时器外声明一个标识接收一下this
var that = this;
//定时器
var timer = setInterval(function(){
//缓存一下
var snake = that.snake;
var food = that.food;
var snakeBody = snake.body;
var snakeHead = snakeBody[snakeBody.length-1];
//获取小蛇移动时的最大值的边界
var map = that.map;
var maxWidthCount = Math.floor(map.offsetWidth / food.width);
var maxHeightCount = Math.floor(map.offsetHeight / food.height);
//调用小蛇移动
that.snake.move();
//--当小蛇移动后,检测小蛇是否吃到食物
//检测蛇头与食物的坐标,如果相同,说明吃到食物
//吃到食物后需要给蛇身中添加一组新的坐标
//通过观察发现,添加的新坐标就是原来蛇尾的坐标
if(snakeHead.x===food.x && snakeHead.y===food.y){
snakeBody.unshift(
{x:snakeBody[0].x,y:snakeBody[0].y,bgColor:"orange"}
);
//吃掉后重新绘制食物
food.init();
};
//检测游戏是否结束(撞墙死)
//检测舍友的坐标与最大坐标值之间的关系
if((snakeHead.x<0 || snakeHead.y<0)||( snakeHead.x>maxWidthCount-1 || snakeHead.y>maxHeightCount-1)){
alert("游戏结束");
clearInterval(timer);
return;
}
//撞到自己死
if(snakeBody.length > 4){
for(var i=snakeBody.length-5;i>=0;i--){
if(snakeHead.x===snakeBody[i].x && snakeHead.y===snakeBody[i].y ){
alert("游戏结束");
clearInterval(timer);
return;
}
}
}
//绘制小蛇
snake.init();
},100);
}
//设置按键操作
Game.prototype.changeDirection = function(){
var that = this;
//给document绑定键盘事件
document.onkeydown = function(e){
var _event = window.event || e;
switch (true){
case _event.keyCode == 37 && that.snake.direction !== "right":
that.snake.direction = "left";
break;
case _event.keyCode == 38 && that.snake.direction !== "down":
that.snake.direction = "up";
break;
case _event.keyCode == 39 && that.snake.direction !== "left":
that.snake.direction = "right";
break;
case _event.keyCode == 40 && that.snake.direction !== "up":
that.snake.direction = "down";
break;
}
}
}
//暴露给全局
window.Game = Game;
})();
//创建了一个游戏对象
var currentMap = document.getElementById('map');
var game = new Game({
food:new Food({map:currentMap}),
snake:new Snake({map:currentMap}),
map:currentMap
});
//开始游戏(初始化)
game.init();
好了,结束,一条简单的小蛇就可以动起来吃东西了。