JavaScript贪吃蛇(一)

完全自己写的贪吃蛇,先试试没有参考别人的方法,自己的思路是怎么样的。

个人觉得贪吃蛇最难的地方是蛇移动,考虑到蛇移动可能转换方向,最好的方式,是把尾部去了截,在头部按当前蛇的方向增加一截,这样看起来蛇就移动了。

具体看注释。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>贪吃蛇</title>
<style>
/*canvas居中*/
#myCanvas {
	position: absolute;
	margin: auto auto;
	top: 5px;
	right: 5px;
	bottom: 5px;
	left: 5px;
	border: 1px solid black;
}
</style>

<script>
//启用javascript严格模式,执行效率高
"use strict";

//定义全局变量
var gird_length=10;//每一格的宽度
var rol_gird=60;//横行60格
var col_grid=40;//一列40格


window.addEventListener("load",function(){
	var myCanvas=document.getElementById("myCanvas");
	var context=myCanvas.getContext("2d");

	//设置canvas宽度
	myCanvas.width=rol_gird*gird_length;
	myCanvas.height=col_grid*gird_length;

	//声明 蛇喜欢吃的点心
	var food;
	//得分
	var score=0;
	

	//格子类
	function Grid(x,y,dir){
		this.color="blue";
		this.strokeColor="white";
		this.x=x;
		this.y=y;
		if(dir==undefined){
			dir="right";
		}
		this.dir=dir;
	};

	


	//格子显示
	Grid.prototype.draw= function(){
		context.save();
		context.fillStyle=this.color;
		context.fillRect(this.x,this.y,gird_length,gird_length);
		//加grid边框
		context.strokeStyle = this.strokeColor;
		context.strokeRect(this.x,this.y,gird_length,gird_length);
		context.restore();
	};

	//格子移动
	Grid.prototype.move= function(){
			if(this.dir==="up"){
				this.y=this.y-gird_length;
			}else if(this.dir==="left"){
				this.x=this.x-gird_length;
			}else if(this.dir==="down"){
				this.y=this.y+gird_length;
			}else if(this.dir==="right"){
				this.x=this.x+gird_length;
			}
			this.draw(this.x,this.y,gird_length,gird_length);
	};

	//格子删除
	Grid.prototype.remove= function(){
		context.clearRect(this.x,this.y,gird_length,gird_length);
		delete this;
	};

	//蛇起始出现位置在(3,3)格
	var snake={
		x:3,
		y:3,
		gridArr:new Array(),//包含格子数组
		dir:"right"
		
	};

	//蛇显示,循环调用格子draw方法
	snake.draw= function(){
		for(var i=0;i<this.gridArr.length;i++){
			this.gridArr[i].draw();
		}
	};
	//蛇移动,本游戏难点所在
	//蛇移动,不是每一个格子向前移动,这样的话不好把握蛇转换方向
	//正确的方法是,把蛇最后一格去掉,按当前方向生成一个新的格子,加到最前面。
	snake.move= function(){

		var lastGrid=this.gridArr.shift();//数组的shift方法,删除array[0],并返回对象
		lastGrid.remove();
		var firstGrid=this.gridArr[this.gridArr.length-1];
		//不允许蛇向反方向移动
		var dir=this.dir;
		if((firstGrid.dir=="up"&&dir=="down")||(firstGrid.dir=="down"&&dir=="up")
				||(firstGrid.dir=="right"&&dir=="left")||(firstGrid.dir=="left"&&dir=="right")){
			//如果蛇向反方向,则无效,按原来方向
			dir=firstGrid.dir;
		}
		var g = new Grid(firstGrid.x,firstGrid.y,dir);//按蛇的方向生成一个新格子。
		g.move();

		//记得把lastGrid加到gridArr,如果不记得调试就可以看出来。
		//没关系,程序是调出来的
		this.gridArr.push(g);
	};

	//蛇吃了点心。向尾部加一个格子,方向和最后一个一样
	snake.eat=function(){
		
		var lastGrid=this.gridArr[0];
		var x=lastGrid.x;
		var y=lastGrid.y;
		//后退一格
		if(lastGrid.dir=="up"){
			y+=gird_length;
		}
		else if(lastGrid.dir=="down"){
			y-=gird_length;
		}else if(lastGrid.dir=="right"){
			x+=gird_length;
		}else if(lastGrid.dir=="left"){
			x-=gird_length;
		}
		
		var g = new Grid(x,y,lastGrid.dir);
		g.move();
		this.gridArr.unshift(g);//Array的unshift方向,向数组0位置插入一个元素
		
	};

	//蛇初始五格
	snake.init=function(){
		
		for(var i=0;i<5;i++){
			this.gridArr.push(new Grid((this.x+i)*gird_length,this.y*gird_length));
		}
		this.draw();

	};

	snake.init();
	randomFood().draw();
	initScore();

	

	//初始化Score
	function initScore(){
		context.font="20px Georgia";
		context.fillText("Score:",3*gird_length,(col_grid-3)*gird_length);
		context.fillText(score,9*gird_length,(col_grid-3)*gird_length);

	}

	
	//更新分数
	function updateScore(){
		score+=10;
		context.clearRect(9*gird_length,(col_grid-5)*gird_length,3*gird_length,gird_length*2);
		context.fillText(score,9*gird_length,(col_grid-3)*gird_length);

	}

	//检测蛇是否检测蛇是否碰到自己和碰到墙
	snake.isDead= function(){
		var arr = this.gridArr;
		//是否碰到自己
		for(var i=0;i<arr.length;i++){
			var gi= arr[i];
			for(var j=0;j<arr.length;j++){
				if(i==j)
					continue;
			var gj=arr[j];
			if(gi.x==gj.x&&gi.y==gj.y)
				return true;
			}
			//是否碰到墙
			if(gi.x<=0||gi.y<=0||gi.x>=myCanvas.width-gird_length||gi.y>=myCanvas.height-gird_length)
				return true;
		}
		return false;
	};

	//定时移动蛇
	window.timer=window.setInterval(function(){
		
		snake.move();
		//每次移动后,首先检测蛇是否碰到自己和碰到墙
		if(snake.isDead()){
			//删除定时器
			clearInterval(timer);
			alert("游戏结束,重新开始,请刷新页面");
		}else{
			//snake每一次移动后就检测下是否吃到food
			if(isCollide()){
				updateScore();
				snake.eat();
				//生成新的foot
				randomFood().draw();
				
			}
		}
		
	},300);

	//按键改变snake方向
	window.addEventListener("keydown",function(e){
		var keyCode=e.keyCode;
		console.log(keyCode);
		if(keyCode===87){
			snake.dir="up";
		}else if(keyCode===68){
			snake.dir="right";
		}
		else if(keyCode===83){
			snake.dir="down";
		}
		else if(keyCode===65){
			snake.dir="left";
		}
			
	});

	

	//碰撞检测
	function isCollide(){
		var arr = snake.gridArr;
		var x=food.x;
		var y=food.y;
		
		for(var i=0;i<arr.length;i++){
			var g= arr[i];
			if(x===g.x&&y===g.y){
				return true;
			}
		}
		return false;
	}

	//随机生成food;
	function randomFood(){
		var r=Math.random();
		var x=parseInt(r*rol_gird);
		var y=parseInt(r*col_grid);
		food= new Grid(x*gird_length,y*gird_length);
		if(isCollide()){
			return randomFood();
		}else
			return food;
	}
	
});

</script>
</head>
<body>

<canvas id="myCanvas"></canvas>

</body>
</html>




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章