用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();
})()
  • 效果展示
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章