原生JavaScript + canvas 實現貪喫蛇小遊戲

效果圖:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>貪喫蛇</title>
	<link rel="stylesheet" href="css/snake.css">
	<script src="js/snake.js"></script>
</head>
<body>
	<div class="snake-wrap">
		<div class="info-bd">
			<div class="info-item">
				得分:<span class="score">0</span>分
			</div>
			<div class="info-item">
				用時:<span class="second">0</span>秒
			</div>

		</div>
		<div class="game-bd">
			<canvas id="gameCan" width="600" height="600"></canvas>
		</div>
		<div class="btn-group">
			<div class="btn">
				<button class="j-start">開始</button>
			</div>
			<div class="btn">
				<button class="j-pause">暫停</button>
			</div>
			<div class="btn">
				<button class="j-reset">重置</button>
			</div>
		</div>
		
	</div>
</body>

</html>
button{
	outline: none;
	border: none;
}
.snake-wrap{
	width: 600px;
	height: 720px;
	margin: 50px auto;
	background: limegreen;
}
.info-bd{
	height: 60px;
}
.info-bd .info-item{
	float: left;
	width: 50%;
	height: 100%;
	text-align: center;;
	font-size: 20px;
	line-height: 60px;
	color: #fff;
}
.game-bd{
	height: 600px;
	background: #000;
}
.btn-group{
	height: 60px;
}
.btn-group .btn{
	width: 33.3%;
	float: left;
	height: 100%;
}
.btn-group .btn button{
	background: transparent;
	width: 100%;
	height: 100%;
	color: #fff;
	font-size: 20px;
	cursor: pointer;
}
.btn-group .btn button:hover{
	background: lime;
}
.btn-group .btn button:disabled{
	background: lightgreen;
}

 

window.onload = function(){
	var can = document.getElementById('gameCan'),
		oStart = document.getElementsByClassName('j-start')[0],
		oPause = document.getElementsByClassName('j-pause')[0],
		oReset = document.getElementsByClassName('j-reset')[0],
		oSecond = document.getElementsByClassName('second')[0],
		oScore = document.getElementsByClassName('score')[0],
		ctx = can.getContext('2d'),
		//畫布width
		cWidth = ctx.canvas.width,
		//畫布Height
		cHeight = ctx.canvas.height,
		//半徑
		r = 10,
		//遊戲用時
		second = 0;
		//定時器
		t = null,
		//得分
		score = 0;
		//用時時間定時器
		st = null,
		//每次移動增加的座標
		size = r * 2,
		//初始蛇的長度
		bodyNum = 3;

	//實例化
	var s = new Snake();
	//鍵盤事件
	document.onkeydown = function(){
		var e = e || window.event;
		var code = e.keyCode;
		if(code === 38){
			s.dir = s.dir !== "DOWN" ? "UP" : "DOWN";
		}else if(code === 40){
			s.dir = s.dir !== "UP" ? "DOWN" : "UP";
		}else if(code === 37){
			s.dir = s.dir !== "RIGHT" ? "LEFT" : "RIGHT";
		}else if(code === 39){
			s.dir = s.dir !== "LEFT" ? "RIGHT" : "LEFT";
		}
		
		
	}
	oPause.onclick = function(){
		pause.call(this);
	}
	oReset.onclick = function(){
		reset.call(this);
	}
	oStart.onclick = function(){
		start.call(this);
	}
	
	

	//構造函數
	function Body(x,y,c){
		this.x = x;//橫座標
		this.y = y;//縱座標
		this.c = c;//color
	}
	Body.prototype.draw = function(){
		//繪製圓形填充色
		ctx.fillStyle = this.c;
		//開始繪製
		ctx.beginPath();
		//繪製圓形
		ctx.arc(this.x + r,this.y + r,r,0,2 * Math.PI,false);
		//填充
		ctx.fill();
	}
	//繪製蛇
	function Snake(){
		this.snakeArr = [];
		this.bodySize = this.snakeArr.length || bodyNum;
		//初始方向
		this.dir = 'DOWN',
		cWidth = cWidth,
		cHeight = cHeight;

		for(var i = 0;i < this.bodySize; i ++){
			this.snakeArr.push(
				new Body(0,i * r * 2,(i === this.bodySize - 1?'red':'green'))
			)
		}
	}

	//讓蛇運動
	Snake.prototype.move = function(){
		//清除畫布
		ctx.clearRect(0,0,cWidth,cHeight);
		var head = this.snakeArr[this.snakeArr.length - 1];//蛇頭
		var _this = this;
		var snakeArr = _this.snakeArr;
		createFood(snakeArr);
		t = setInterval(function(){
			for(var i = 0; i <_this.snakeArr.length; i++){
				ctx.clearRect(snakeArr[i].x,snakeArr[i].y,size,size);
				if( i !== snakeArr.length - 1){
					//第一個座標等於第二個座標 變更座標
					snakeArr[i].x = snakeArr[i + 1].x;
					snakeArr[i].y = snakeArr[i + 1].y;
				}
			}
			//判斷方向以及座標變換
			if(_this.dir === "DOWN"){
				head.y = head.y == cHeight ? 0 : (head.y + size);
			}else if(_this.dir === "UP"){
				head.y = head.y == -size ? (cHeight - size) : (head.y - size);
			}else if(_this.dir === "RIGHT"){
				head.x = head.x == cWidth ? 0 : (head.x + size);
			}else if(_this.dir === "LEFT"){
				head.x = head.x == -size ? (cWidth - size) : (head.x - size);
			}

			for(var i = 0; i < snakeArr.length; i++){
				//繪製圓
				snakeArr[i].draw();
				if( i != snakeArr.length - 1){
					//判斷蛇頭碰到蛇身體
					if(head.x === snakeArr[i].x && head.y === snakeArr[i].y){
						//清除定時器
						clearInterval(t);
						ctx.clearRect(0,0,cWidth,cHeight);
						alert("GAME OVER");
						reset();
						return;
					}
				}
			}
			//蛇喫到食物
			if(s.foodX === head.x && s.foodY === head.y){
				var x,
					y;
				score ++;
				oScore.innerText = score;
				createFood(snakeArr);
				if(snakeArr[0].x === snakeArr[1].x){
					x = snakeArr[0].x;
					if(snakeArr[0].y > snakeArr[1].y){
						y = snakeArr[0].y + size;
					}else if(snakeArr[0].y < snakeArr[1].y){
						y = snakeArr[0].y - size;
					}
				}else if(snakeArr[0].y === snakeArr[1].y){
					y = snakeArr[0].y;
					if(snakeArr[0].x > snakeArr[1].x){
						x = snakeArr[0].x + size;
					}else if(snakeArr[0].x < snakeArr[1].x){
						x = snakeArr[0].x - size;
					}
				}
				snakeArr.unshift(new Body(x,y,'green'));
			}

		},200)
	}

	//繪製食物
	function createFood(snakeArr){
		s.foodX = setRandPos().x;
		s.foodY = setRandPos().y;
		for(var i = 0; i <snakeArr.length; i++){
			if(s.foodX === snakeArr[i].x && s.foodY === snakeArr[i].y){
				s.foodX = setRandPos().x;
				s.foodY = setRandPos().y;
			}
		}
		new Body(s.foodX,s.foodY,'yellow').draw();

	}
	//食物的隨機座標
	function setRandPos(){
		var arr = [];
		for(var i = 0; i < cWidth - size;i++){
			if(i%size == 0){
				arr.push(i);
			}
		}

		return {
			x:arr[Math.floor(Math.random() * arr.length +1) - 1],
			y:arr[Math.floor(Math.random() * arr.length +1) - 1]
		}
	}

	function start(){
		s.move();
		this.disabled = "disabled";
		oPause.disabled = "";
		st = setInterval(function(){
			second ++;
			oSecond.innerText = second;
		},1000)
	}
	function pause(){
		clearInterval(st);
		clearInterval(t);
		this.disabled = "disabled";
		oStart.disabled = "";
	}
	function reset(){
		clearInterval(st);
		clearInterval(t);
		oStart.disabled = "";
		oPause.disabled = "";
		oSecond.innerText = 0;
		oScore.innerText = 0;
		ctx.clearRect(0,0,cWidth,cHeight);
		s = new Snake();
	}
}


想要獲得更多資料的  請微信搜索公衆號 【熱血科技】,關注一下即可。

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