這次我們用canvas來(lái)制作一個(gè)簡(jiǎn)單的貪吃蛇游戲蛋铆。我們需要學(xué)習(xí)了解canvas的基礎(chǔ)知識(shí)和如何來(lái)創(chuàng)建矩形馋评。
1、游戲需要的游戲
? ? (1)蛇
? ? (2)食物
? ? (3)食物被吃掉后隨機(jī)位置出現(xiàn)
? ? (4)食物不能隨機(jī)出現(xiàn)再蛇身上
? ? (5)蛇能動(dòng)刺啦,碰到食物就變長(zhǎng)
? ? (6)蛇頭碰到蛇身和碰到墻就結(jié)束
2、游戲思路
????(1)要有蛇(畫(huà)蛇)
? ? ? ? a.蛇頭
? ? ? ? b.蛇身
? ? (2)讓蛇動(dòng)起來(lái)
? ? ? ? ?a.默認(rèn)的開(kāi)啟游戲的時(shí)候有一個(gè)方向
????????b.鍵盤能控制方向
????????c.animate定時(shí)器
????(3)有食物 隨機(jī)投放
????????a.產(chǎn)生隨機(jī)的位置
? ? ? ? b.判斷位置是否在蛇頭或者蛇身上蜕青,如果在重新產(chǎn)生位置右核,如果不在畫(huà)食物
????(4)吃食物
? ? ? ? ?a.判斷遲到食物 碰撞檢測(cè)
????????b.吃到食物添加蛇身
? ? ?(5)判斷游戲結(jié)束
????????a.蛇頭碰到蛇身
????????b.蛇頭碰到墻壁
3.代碼
我們首先要?jiǎng)?chuàng)建一個(gè)canvas,游戲要在畫(huà)布上實(shí)現(xiàn)宗兼,HTML部分如下:
<!DOCTYPE html>
<html lang="en">
????<head>
????????<meta charset="UTF-8">
????????<title>Document</title>
????????<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.js"></script>
????????<style>
????????????canvas{
????????????????box-shadow: 0 0? 10px #000;
????????????????display: block;
????????????????margin:20px auto;
? ? ? ? ? ?}
????????</style>
</head>
<body>
????<canvas width="1200" height="800" id="canvas"></canvas>
</body>
</html>
第一步創(chuàng)建蛇頭蛇身?挠他,添加蛇默認(rèn)的運(yùn)動(dòng)方向
// 蛇頭(準(zhǔn)備創(chuàng)建的方塊)的元素
function Rect(x,y,width,height,color){
????this.x = x;
????this.y = y;
????this.width = width;
????this.height = height;
????this.color = color;
}
// 完善矩形 繪制矩形
Rect.prototype.draw = function(){
????// 開(kāi)始繪畫(huà)矩形
????Draw.prototype.xt.beginPath();
????// 畫(huà)筆顏色
????Draw.prototype.xt.fillStyle = this.color;
????// 填充矩形
????Draw.prototype.xt.fillRect(this.x,this.y,this.width,this.height);
????// 描邊
????Draw.prototype.xt.strokeRect(this.x,this.y,this.width,this.height);
}
????// 構(gòu)造對(duì)象蛇
????function Snake(obj){
????// 畫(huà)蛇頭 蛇頭的顏色是紅色的
????this.head = new Rect(obj.canvas.width/2-20,obj.canvas.height/2-20,40,40,'red');
????//定義一個(gè)空數(shù)組存放組成整蛇的方塊對(duì)象
????this.body = [];
????//表示多個(gè)身體
????// 蛇身的x比蛇頭移動(dòng)
????40 var x = this.head.x-40;
????// 距離y不變
????var y = this.head.y;
????// 循環(huán)創(chuàng)建身體 默認(rèn)蛇的長(zhǎng)度是3
????for (var i = 0; i < 3; i++) {
????// 每吃一個(gè)東西蛇身會(huì)加一個(gè) 蛇身的顏色是灰色的
????var rect = new Rect(x,y,40,40,'gray');
????this.body.push(rect);
????x-=40;
}
}
????// 添加蛇默認(rèn)的運(yùn)動(dòng)方向 向右
????// 公有屬性,任何地方能夠修改方向
????Snake.prototype.direction = 1;
????// 定義一個(gè)是否吃到食物的標(biāo)記
????Snake.prototype.isEatFood = false;
????// 畫(huà)蛇方法
????Snake.prototype.draw = function(){
????// 畫(huà)蛇頭
????this.head.draw();
????// 循環(huán)創(chuàng)建蛇身
????for (var i = 0; i < this.body.length; i++) {
????this.body[i].draw();
}
}
第二步讓蛇動(dòng)起來(lái)篡帕,里面包含風(fēng)道墻壁和蛇頭蛇身然后就游戲結(jié)束
// 蛇移動(dòng)的方法
Snake.prototype.move = function(){
????// 檢測(cè)碰撞到墻壁
????if (this.head.x<40 || this.head.y<-40 || this.head.x>$('#canvas')[0].width-40-40 || ????this.head.y>$('#canvas')[0].height-40-40) {
????????return false;
????}
????// 檢測(cè)蛇頭與蛇身
????for (var i =0;i<this.body.length;i++) {
????????console.log(this.body[i])殖侵;
????????if (isRectHit(this.head,this.body[i])) {
????????????return false;
????????}
}
// 加一個(gè)頭
var rect = new Rect(this.head.x,this.head.y,40,40,'gray');
// 添加身體開(kāi)始的地方
this.body.splice(0,0,rect);
// 去掉一個(gè)尾巴,
if (Snake.prototype.isEatFood) {
????Snake.prototype.isEatFood = false;
????// 重新隨機(jī)產(chǎn)生食物
}else{
????this.body.pop();
}
switch(this.direction){
????case 0:
????????this.head.y -= 40
????????break;
????case 1:
????????this.head.x += 40
????????break;
????case 2:
????????this.head.y +=40
????????break;
case 3:
????????this.head.x -= 40
????????break;
}
return true;
第三步食物
// 添加鍵盤監(jiān)聽(tīng)
$(window).keydown(function(e){
????switch(e.keyCode){
????????case 37:
????????// 如果當(dāng)前的方向是向右的,不能改為向左
????????if (Snake.prototype.direction == 1) {
????????????return;
????????}
????????Snake.prototype.direction = 3;
????????break;
????????case 38:
????????// 如果當(dāng)前的方向是向下的镰烧,不能改為向上
????????????if (Snake.prototype.direction == 2) {
????????????????return;
???????????}
????????????Snake.prototype.direction = 0;
????????????break;
????????case 39:
????????????if (Snake.prototype.direction == 3) {
????????????????return;
????????????}
????????????Snake.prototype.direction = 1;
????????????break;
? ? ? ? case 40:
????????????if (Snake.prototype.direction == 0) {
????????????????return;
????????????}
????????????Snake.prototype.direction = 2;
????????????break;
????}
})
// 隨機(jī)產(chǎn)生食物
function randFood(snake){
????// 是否在蛇身上
????isInSnake = true;
????while(isInSnake){
????????// 產(chǎn)生兩個(gè)位置
????????x,y var x = getRandPosition(0,($('#canvas')[0].width-40)/40)*40;
????????var y = getRandPosition(0,($('#canvas')[0].height-40)/40)*40;
????????// 創(chuàng)建食物矩形
????????var food = new Rect(x-20,y-20,40,40,'green');
????????isInSnake = false;
????????// 判斷食物是否在蛇身
????????// 是否是蛇頭
????????if (isRectHit(food,snake.head)) {
????????????isInSnake = true;
????????????continue;
????????}
????????// 是否是蛇身
????????for (var i=0; i < snake.body.length; i++) {
????????????if (isRectHit(food,snake.body[i])) {
????????????????????isInSnake = true;
????????????????????break;
????????????}
????????}
????}
????return food;
}
// 產(chǎn)生隨機(jī)數(shù)的函數(shù)也就是隨機(jī)產(chǎn)生食物
function getRandPosition(min,max){
????return Math.round(Math.random()*(max-min)+min);
}
// 判斷矩形是否重合
function isRectHit(rect1,rect2){
????var R1_min_x = rect1.x;
????var R1_min_y = rect1.y;
????var R2_min_x = rect2.x;
????var R2_min_y = rect2.y;
????var R1_max_x = rect1.x + 20;
????var R2_max_x = rect2.x + 20;
????var R1_max_y = rect1.y + 20;
????var R2_max_y = rect2.y + 20;
// 兩個(gè)圖形的最大邊界和最小邊界? 就是食物和蛇頭的碰撞
????var min_x = Math.max(R1_min_x,R2_min_x);
????var max_x = Math.min(R1_max_x,R2_max_x);
????var min_y = Math.max(R1_min_y,R2_min_y);
????var max_y = Math.min(R1_max_y,R2_max_y);
????if (min_x<max_x&&min_y<max_y) {
????????return true;
????}else{
????????return false;
????}
}
var draw = new Draw($('#canvas')[0]);
//創(chuàng)建一個(gè)繪圖的實(shí)例對(duì)象
draw.main();
//調(diào)用main繪制圖像
});
4拢军、效果圖如下:
以上是貪吃蛇游戲的全部代碼,雖然代碼很詳細(xì)但大家還需要認(rèn)認(rèn)真真理解怔鳖,希望本文對(duì)大家有所啟發(fā)茉唉,不懂的地方可以問(wèn)我。