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>




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