JS-贪吃蛇分析

460 阅读1分钟

贪吃蛇

1、分析

小游戏中共有三个对象。一个是地图(Map)、一个是食物(Food)、一个是蛇(Snake)。

以面向对象的方式来开发,应该创建三个对象。

每个对象的特点:

地图Map:
  • 宽width

  • 高height

  • 背景颜色backgroundColor

  • 显示方法:show

  • 地图属性:保存生成的地图(后续需要向地图中添加食物和小蛇)

食物Food:
  • 宽width

  • 高height

  • 背景颜色backgroundColor

  • x轴坐标(根据地图宽/食物宽):0~29(每个坐标实际像素是20px)

  • y轴坐标(根据地图高/食物高):0~19(每个坐标实际像素是20px)

  • 显示方法:show

  • 食物属性:保存生成的食物(小蛇吃食物、食物刷新时需要用到)

蛇Snake:
  • 身体body(默认有三个div组成,其中一个蛇头,两段蛇身,都有颜色)(数组类型)

  • 单节宽 width

  • 单节高 height

  • 单节x坐标

  • 单节y坐标

  • 移动方向 direction

  • 显示方法:show

  • 能够移动move方法(能够拐弯,改变移动方向;能够吃食物,变长)

2、创建地图div
3、创建食物div
4、创建蛇div
5、让蛇移动
6、让蛇拐弯
7、让蛇吃食物
8、让蛇加速
9、边界判断
10、蛇不能碰身体
11、连续按键无效
Code
<!DOCTYPE html>
<html>
<head>
  	<meta charset="utf-8">
	<title>贪吃蛇</title>
	<style type="text/css">
		body{margin:0;}
	</style>
</head>
<body>
<script type="text/javascript">
	//创建地图
	function Map(){
		//属性
		this.width = 600;
		this.height = 400;
		this.backgroundColor = 'gray';
		this.ditu = null;

		//方法
		//创建地图并显示
		// this.show = function(){

		// }
		if(!Map.prototype.show){
			Map.prototype.show = function(){
				//创建div 
				var div = document.createElement('div');
				//设置样式
				div.style.width = this.width + 'px';
				div.style.height = this.height + 'px';
				div.style.backgroundColor = this.backgroundColor;
				//显示到页面中
				document.body.appendChild(div);
				//将地图的div 保存到地图对象的属性上,后续需要使用
				this.ditu = div;
			}
		}
		
	}
	// Map.prototype.show = function(){

	// }
	var map = new Map();
	map.show();
	// console.log(map.ditu);
	
	// 创建食物
	function Food(map){
		//属性
		this.width = 20;
		this.height = 20;
		this.backgroundColor = 'green';
		this.x = 0;
		this.y = 0;
		this.position = 'absolute';
		this.shiwu = null;
		//方法
		//创建div并显示
		if(!Food.prototype.show){
			Food.prototype.show = function(){
				//加上判断,一个方法 兼具显示和刷新功能
				if(!this.shiwu){
					//div没有创建过
					//创建div 
					var div = document.createElement('div');
					//设置样式
					div.style.width = this.width + 'px';
					div.style.height = this.height + 'px';
					div.style.backgroundColor = this.backgroundColor;
					div.style.position = 'absolute';
					//显示到页面中
					map.ditu.appendChild(div);
					//将地图的div 保存到地图对象的属性上,后续需要使用
					this.shiwu = div;
				}
				
				//位置 生成随机的x y坐标
				//横坐标x 0-30之间(不能包含30)的整数,乘以20倍(食物宽度),就是到页面左边的距离 
				//纵坐标y 0-20之间(不能包含20)的整数,乘以20倍(食物高度),就是到页面顶部的距离
				this.x = Math.floor( Math.random() * (map.width/this.width) );
				this.y = Math.floor( Math.random() * (map.height/this.height) );
				//设置位置相关的样式
				this.shiwu.style.left = this.x * this.width + 'px';
				this.shiwu.style.top = this.y * this.height + 'px';
				
			}
		}
	}

	var food = new Food(map);
	food.show();

	//创建蛇
	function Snake(){
		//属性
		//身体  [[x坐标,y坐标,颜色,div], [x坐标,y坐标,颜色,null], [x坐标,y坐标,颜色,null]]
		//蛇 默认 水平放,蛇头向右
		this.body = [[5, 3, 'red', null], [4, 3, 'blue', null], [3, 3, 'blue', null]];
		this.width = 20;
		this.height = 20;
		this.position = 'absolute';
		this.direction = 'right';
		this.canChange = false;//是否可以改变方向
		//方法 显示、移动
		if(!Snake.prototype.show){
			Snake.prototype.show = function(){
				//创建每节身体的div
				for(var i=0; i<this.body.length; i++){
					// this.body[i] //每节身体信息,是一个数组[5, 3, 'red']
					if(!this.body[i][3]){
						//以前没有创建过对应的div
						var div = document.createElement('div');
						//设置样式
						div.style.width = this.width + 'px';
						div.style.height = this.height + 'px';
						div.style.position = this.position;
						//显示到地图中
						map.ditu.appendChild(div);
						this.body[i][3] = div;
					}
					
					this.body[i][3].style.backgroundColor = this.body[i][2];
					this.body[i][3].style.left = this.body[i][0] * this.width + 'px';
					this.body[i][3].style.top = this.body[i][1] * this.height + 'px';
				
				}
				//显示完成,可以修改方向
				this.canChange = true;
			}
			//让蛇移动 每一节身体坐标,变成前一节坐标
			//从蛇尾开始移动,蛇头单独控制方向
			Snake.prototype.move = function(){
				//循环,修改每节身体的坐标(先不管蛇头)
				// for(var i=0; i<this.body.length; i++){
				// 	 // 0 1 2
				// 	// this.body[this.body.length-1-i]
				// }
				for(var i=this.body.length-1; i>0; i--){
					// this.body[i]
					this.body[i][0] = this.body[i-1][0];
					this.body[i][1] = this.body[i-1][1];
				}
				//蛇头控制方向(用方向判断,蛇头的坐标怎么改)
				if(this.direction == 'right'){
					//蛇头横坐标+1
					this.body[0][0] += 1;
				}else if(this.direction == 'left'){
					//蛇头横坐标-1
					this.body[0][0] -= 1;
				}else if(this.direction == 'down'){
					//蛇头纵坐标+1
					this.body[0][1] += 1;
				}else if(this.direction == 'up'){
					//蛇头纵坐标-1
					this.body[0][1] -= 1;
				}
				//判断边界条件
				if(this.body[0][0] < 0 || this.body[0][0] > 29 || this.body[0][1] < 0 || this.body[0][1] > 19){
					//游戏结束 停止定时器
					clearInterval(timer);
					alert('game over');
					return;
				}
				//判断 蛇头是否和其他的身体坐标重合
				for(var i=1; i<this.body.length; i++){
					if(this.body[0][0] == this.body[i][0] && this.body[0][1] == this.body[i][1]){
						//蛇头和身体重合
						////游戏结束 停止定时器
						clearInterval(timer);
						alert('game over');
						return;
					}
				}
				//重新显示
				this.show();
				//判断是否吃到食物  蛇头坐标和食物完全一样
				if(this.body[0][0] == food.x && this.body[0][1] == food.y){
					//吃到食物,将this.body 加长一节
					this.body[this.body.length] = [0, 0, 'blue', null];
					// this.body.push([0, 0, '', null]);
					//食物刷新位置
					food.show();
					//吃到食物,让蛇加速
					if(t > 150){
						t -= 50;
						setTimer();
					}
				}
			}
		}
	}
	var snake = new Snake();
	snake.show();

	//让蛇自动走  设置定时器
	var t = 500;
	var timer;
	function setTimer(){
		//先停止之前的定时器
		clearInterval(timer);
		//重新设置定时器
		timer = setInterval(function(){
			snake.move();
		}, t);
	}
	setTimer();
	

	//让蛇拐弯
	//绑定键盘事件
	window.onkeyup = function(e){
		var evt = e || window.event;
		if(!snake.canChange){
			//不能改方向
			return;
		}
		// console.log(evt);// 左 37 上38 右39 下40
		if(e.keyCode == 37 && snake.direction != 'right'){
			snake.direction = 'left';
		}else if(e.keyCode == 38 && snake.direction != 'down'){
			snake.direction = 'up';
		}else if(e.keyCode == 39 && snake.direction != 'left'){
			snake.direction = 'right';
		}else if(e.keyCode == 40 && snake.direction != 'up'){
			snake.direction = 'down';
		}

		snake.canChange = false;
	}
</script>
</body>
</html>