用JavaScript写贪吃蛇案例

  • html部分
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>贪吃蛇</title>
	<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
	<div id="map"></div>
	<script type="text/javascript" src="js/tools.js"></script>
	<script type="text/javascript" src="js/Food.js"></script>
	<script type="text/javascript" src="js/snake.js"></script>
	<script type="text/javascript" src="js/game.js"></script>
	<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
  • css部分
#map{
	width: 800px;
	height: 600px;
	background-color: lightgray;
	position: relative;
}
  • tool.js部分
//工具对象就一个,不需要创建构造函数
(function(){
var Tools = {
	//写一个方法获取随机数
  getRandom: function (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) +  min;
  }
}	
//暴露Tools给window
window.Tools = Tools;
})()

  • food.js部分
//所有js文件中书写代码,都是全局作用域


//自调用函数————————开启新的作用域,可以避免命名冲突
// (function(){

// })()

(function(){
//对象————蛇 , 食物 ,游戏对象(控制游戏逻辑)
var position = 'absolute';
var elements = [];//页面上显示的元素



//1.创建食物对象——属性:座标  大小  颜色
//             ——方法:rendrt(随机创建一个食物对象,并输出到map上)
//创建食物的构造函数
function Food(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 || 'red';
}
//写render方法
Food.prototype.render = function(map){//这个map表示父容器
	//删除之前创建的元素
	remove();
	//创建div
	var div = document.createElement('div'); 
	map.appendChild(div);
	elements.push(div);


	this.x = Tools.getRandom(0,map.offsetWidth/this.width - 1)*this.width;
	this.y = Tools.getRandom(0,map.offsetHeight/this.height - 1)*this.height;
	
	//设置div的样式
	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.backgroundColor = this.color;
	div.style.position = 'absolute';




}
function remove(){
	for(var i = elements.length-1;i>=0;i--){
	//2删除页面上的div(从最后一项开始删直到i=0为止)
		elements[i].parentNode.removeChild(elements[i]);
	//1删除数组中的元素(第一个参数表示从哪个元素开始删除,第二个元素表示删除几个元素)
		elements.splice(i,1);
	}
}
//为了使外部函数可以调用Food构造函数(可以通过window,但是window是可以shenglue的)
window.Food = Food;
})()

		var map = document.getElementById('map');
		var food = new Food();
		food.render(map);
  • snake.js部分
//蛇对象——————属性:蛇节大小 初始时是三节(蛇头——红色)
//				  移动	(方向)
//				  蛇的身体——数组(包括蛇的头部和身体,第一个位置是蛇头)	
//		——————方法:渲染	(将蛇渲染到map上)	  		

(function(){//自调用函数,开启一个新的局部作用域,防止命名冲突
	var position = 'absolute';
	var elements = []//记录之前创建的蛇
function Snake(options){
	options = options || {};
	this.width = options.width || 20;
	this.height = options.height || 20;
	this.direction = options.direction || 'right';
	//第一部分是蛇头
	this.body = [
	{x:3,y:2,color:'red'},
	{x:2,y:2,color:'blue'},
	{x:1,y:2,color:'blue'}

	];
}
//蛇具有的方法
Snake.prototype.render = function(map){
	//删除之前创建的蛇
	remove();
	//把每一个蛇节渲染到地图上
	for(var i = 0,len = this.body.length;i<len;i++){
		//取出蛇节
		var object = this.body[i];//object中记录蛇节的大小和位置
		//每一个蛇节显示出来
		var div = document.createElement('div');
		map.appendChild(div);
		//记录当前蛇节
		elements.push(div);
		//注意——要设置div的位置,必须要设置div的position使其脱离文档流
		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.backgroundColor = object.color;
	}
}
	//私有成员
	function remove(){
		//把记录的蛇删除
		//删除数组的每一项(不能从前往后)
		for(var i = elements.length-1;i>=0;i--){
			//删除div
			elements[i].parentNode.removeChild(elements[i]);
			//删除数组中的元素
			elements.splice(i,1);
		}
		
	}
	//控制蛇移动的方法(当前蛇节到上一个蛇节的位置)
Snake.prototype.move = function(food,map){
	for (var 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;

	}
	//控制蛇头的移动
	//判断蛇头移动的方向
	var head = this.body[0];
	switch(this.direction){
		case 'right':
			head.x+=1;
			break;
		case 'left':
			head.x -=1;
			break;

		case 'top':
			head.y -=1;
			break;

		case 'bottom' :
			head.y +=1;
			break;

	}
	//2.3当蛇遇到食物的时候 做出相应的处理
	//变化——蛇身变长, 食物消失,再重新随机生成一个食物
	//蛇头的座标
	//head.x表示前面距离左边有几个蛇节的宽度
	var headX = head.x * this.width;
	var headY = head.y * this.height;
	if(headX == food.x && headY == food.y){
		//让蛇增加一节
		//获取蛇的最后一节
		var last = this.body[this.body.length-1];
		this.body.push({
			x:last.x,
			y:last.y,
			color:last.color
		})
		//随机在地图上重新生成食物
		food.render(map);
	}
}
	//暴露构造函数给外部
	window.Snake = Snake;
})()		


  • game.js部分
//游戏对象——————属性:食物 
//                  蛇 
//				    map(将食物与蛇渲染到蛇上面)
//				方法:start(开始游戏)


(function(){
	var that;//用于记录游戏对象
	//构造函数
	function Game(map){
		this.food = new Food();
		this.snake = new Snake();
		this.map = map;
		that = this;//that值记录游戏对象,然后在自调用函数的任何位置都可以调用
	}
	Game.prototype.start = function(){
		//1.将蛇与食物渲染到地图上去
		this.food.render(this.map);
		this.snake.render(this.map);

		// this.snake.move();
		// this.snake.render(this.map);
		// this.snake.move();
		// this.snake.render(this.map);
		// this.food.render(this.map);
		// this.snake.move();
		// this.snake.move();
		// 
		//2.1让蛇移动起来
		runSnake();
		//2.2通过键盘能控制蛇移动的方向
		bindKey();
		//2.3吃到食物的时候
		//在蛇的move方法中调用此方法
	}
		//2.开始游戏的逻辑
		//2.1让蛇移动起来
		//2.2通过键盘能控制蛇移动的方向
		//2.3当蛇遇到食物的时候 做出相应的处理
		//2.4当蛇到边界的时候游戏结束


		//2.开始游戏的逻辑
		//私有函数
		function runSnake(){
			var timerId = setInterval(function(){
		
				//让蛇移动一次
				//在定时器的function中this指向window对象,所以在这里不能用this
				this.snake.move(this.food,this.map);
				this.snake.render(this.map);//需要将蛇渲染到指定的容器中去
		//2.4当蛇到边界的时候游戏结束
		//获取蛇头的座标
		//横向能够容纳多少个蛇节
		//snake.width表示蛇节的宽度
		var maxX = this.map.offsetWidth / this.snake.width;
		var maxY = this.map.offsetHeight / this.snake.height;

		var headX = this.snake.body[0].x;
		var headY = this.snake.body[0].y;
		if(headX < 0 || headX >= maxX){
			alert('game over');
			clearInterval(timerId);
		}
		if(headY < 0 || headY >= maxY){
			alert('game over');
			clearInterval(timerId);
		}
			}.bind(that),150);
		}
		function bindKey(){
			//注册事件的方式
			//document.keydown = function(){};//第一种
			//第二种方式
			document.addEventListener('keydown',function(e){
				//console.log(e.keyCode);
				//37——左
				//38——上
				//39——右
				//40——下
			switch(e.keyCode){
				case 37:
				this.snake.direction = 'left';
				break;
				case 38:
				this.snake.direction = 'top';
				break;
				case 39:
				this.snake.direction = 'right';
				break;
				case 40:
				this.snake.direction = 'bottom';
				break;
			}
			}.bind(that),false);//当false时是事件冒泡,true时是事件捕获
				
		}

		

		
	window.Game = Game;
})();


  • main.js部分
//程序的入口
//获取地图
(function(){
var map = document.getElementById('map');
var game = new Game(map);
game.start();
})()
  • 效果展示
    在这里插入图片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章