<body onLoad="init();">
<canvas id="canvas" width="384" height="512" style="margin-top: 8px;">
Your browser doesn't support the HTML5 element canvas.
</canvas>
</body>
canvas標(biāo)簽的設(shè)定,用于繪制圖像。
var fps=30; //游戲的幀數(shù),推薦在30~60之間
function init(){ctx=document.getElementById('canvas').getContext('2d'); ctx.lineWidth=2;canvas=document.getElementById("canvas");setInterval(run,1000/fps);
}游戲主邏輯run()將會(huì)以每秒fps幀的速度執(zhí)行,這和后面繪制移動(dòng)物體有關(guān)。
另一些全局變量的設(shè)置,詳細(xì)含義后面還會(huì)提到 var boxx=0;
var boxy=0;
var boxwidth=384;
var boxheight=512;
var backgroundwidth=384;
var backgroundheight=448;
var groundwidth=18.5;
var groundheight=64;
var birdwidth=46;
var birdheight=32;
var birdx=192-birdwidth;
var birdy=224-birdheight;
var birdvy=0; //鳥(niǎo)初始的y軸速度
var gravity=1; //重力加速度
var jumpvelocity=11; //跳躍時(shí)獲得的向上速度
var pipewidth=69; //管道的寬度
var blankwidth=126; //上下管道之間的間隔
var pipeinterval=pipewidth+120; //兩個(gè)管道之間的間隔
var birdstate;
var upbackground;
var bottombackground;
var birdimage;
var pipeupimage;
var pipedownimage;
var pipenumber=0; //當(dāng)前已經(jīng)讀取管道高度的個(gè)數(shù)
var fps=30; //游戲的幀數(shù),推薦在30~60之間
var gamestate=1; //游戲狀態(tài):0--未開(kāi)始,1--已開(kāi)始。2--已結(jié)束
var times;
var canvas;
var ctx;
var i;
var bottomstate;
var pipeheight=[];
var pipeoncanvas=[ //要顯示在Canvas上的管道的location和height[0,0],[0,0],[0,0]];
var backgroundwidth=384;
var backgroundheight=448;
var upbackground;
function init(){ upbackground=new Image();upbackground.src="images/background.png";ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight);
}下方動(dòng)態(tài)的地面較為復(fù)雜,先貼出代碼 //繪制下方的動(dòng)態(tài)背景
function drawmovingscene(){if(bottomstate==1){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*i,backgroundheight,groundwidth,groundheight);bottomstate=2;}else if(bottomstate==2){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.25),backgroundheight,groundwidth,groundheight);bottomstate=3;}else if(bottomstate==3){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.5),backgroundheight,groundwidth,groundheight);bottomstate=4;}else if(bottomstate==4){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.75),backgroundheight,groundwidth,groundheight);bottomstate=1;}
}我這里找到的地面圖片是這個(gè)樣子的。因此想要繪制以下的完整地須要先計(jì)算出多少條能將下部填滿,使用了 for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*i,backgroundheight,groundwidth,groundheight);就繪制出了下方地面的一幀圖像,想要讓地面動(dòng)起來(lái),我選擇每一幀都讓繪制的圖片向左移動(dòng)1/4寬度,這樣就能夠在游戲執(zhí)行時(shí)顯示地面在移動(dòng)。這里使用了一個(gè)bottomstate狀態(tài)量,以此來(lái)記錄當(dāng)前地面的繪制狀態(tài),每次加1。到4后下一幀變?yōu)?。
//隨機(jī)生成管道高度數(shù)據(jù)
function initPipe(){for(i=0;i<200;i++)pipeheight[i]=Math.ceil(Math.random()*216)+56;//高度范圍從56~272for(i=0;i<3;i++){ pipeoncanvas[i][0]=boxwidth+i*pipeinterval;pipeoncanvas[i][1]=pipeheight[pipenumber];pipenumber++;}
}鑒于管道在畫(huà)面中不會(huì)同一時(shí)候出現(xiàn)4個(gè),因此我首先取三個(gè)管道高度數(shù)據(jù)放入pipecanvas數(shù)組,并依據(jù)畫(huà)面的寬度和管道的間隔生成管道位置,為繪制管道作準(zhǔn)備,這是pipecanvas的結(jié)構(gòu) var pipeoncanvas=[ //要顯示在Canvas上的管道的location和height[0,0],[0,0],[0,0]];
以下就要對(duì)管道進(jìn)行繪制了,先實(shí)現(xiàn)一根管道上下兩部分的繪制
//使用給定的高度和位置繪制上下兩根管道
function drawPipe(location,height){//繪制下方的管道ctx.drawImage(pipeupimage,0,0,pipewidth*2,height*2,location,boxheight-(height+groundheight),pipewidth,height);//繪制上方的管道ctx.drawImage(pipedownimage,0,793-(backgroundheight-height-blankwidth)*2,pipewidth*2,(backgroundheight-height-blankwidth)*2,location,0,pipewidth,backgroundheight-height-blankwidth);
}函數(shù)比較簡(jiǎn)單不再贅述,在run函數(shù)中增加drawAllPipe函數(shù)。來(lái)繪制要顯示的三根管道 //繪制須要顯示的管道
function drawAllPipe(){for(i=0;i<3;i++){pipeoncanvas[i][0]=pipeoncanvas[i][0]-4.625;}if(pipeoncanvas[0][0]<=-pipewidth){pipeoncanvas[0][0]=pipeoncanvas[1][0];pipeoncanvas[0][1]=pipeoncanvas[1][1];pipeoncanvas[1][0]=pipeoncanvas[2][0];pipeoncanvas[1][1]=pipeoncanvas[2][1];pipeoncanvas[2][0]=pipeoncanvas[2][0]+pipeinterval;pipeoncanvas[2][1]=pipeheight[pipenumber];pipenumber++;}for(i=0;i<3;i++){drawPipe(pipeoncanvas[i][0],pipeoncanvas[i][1]);}
}這里會(huì)先推斷第一根管道是否已經(jīng)移出畫(huà)布,假設(shè)移出了畫(huà)布則后面的管道數(shù)據(jù)向前順延,并將新的管道高度讀入第三根管道,處理完后按順序意思繪制三根管道。
var highscore=0; //得到過(guò)的最高分
var score=0 //眼下得到的分?jǐn)?shù)//通過(guò)了一根管道加一分if(birdx+birdwidth>pipeoncanvas[0][0]-movespeed/2&&birdx+birdwidth<pipeoncanvas[0][0]+movespeed/2||birdx+birdwidth>pipeoncanvas[1][0]-movespeed/2&&birdx+birdwidth<pipeoncanvas[1][0]+movespeed/2){playSound(scoresound,"sounds/point.mp3");score++;}function drawScore(){ctx.fillText(score,boxwidth/2-2,120);
}在繪制文本之前須要先指定字體和顏色 ctx.font="bold 40px HarlemNights"; //設(shè)置繪制分?jǐn)?shù)的字體 ctx.fillStyle="#FFFFFF";開(kāi)始時(shí)的提示和結(jié)束的計(jì)分板都是普通的圖片,計(jì)分板上用兩個(gè)文本繪制了當(dāng)前分?jǐn)?shù)和得到的最高分?jǐn)?shù) function drawTip(){ctx.drawImage(tipimage,birdx-57,birdy+birdheight+10,tipwidth,tipheight);
}//繪制分?jǐn)?shù)板
function drawScoreBoard(){//繪制分?jǐn)?shù)板ctx.drawImage(boardimage,boardx,boardy,boardwidth,boardheight); //繪制當(dāng)前的得分ctx.fillText(score,boardx+140,boardheight/2+boardy-8);//132//繪制最高分ctx.fillText(highscore,boardx+140,boardheight/2+boardy+44);//184
}這里的最高分highscroe會(huì)在每次游戲結(jié)束時(shí)更新 //刷新最好成績(jī)
function updateScore(){if(score>highscore)highscore=score;
}
<audio id="flysound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="scoresound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="hitsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="deadsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="swooshingsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>為了時(shí)播放音效時(shí)不發(fā)生沖突,我為每一個(gè)音效定義了一個(gè)audio標(biāo)簽,這樣在使用中就不會(huì)出現(xiàn)故障。
然后將定義的變量與標(biāo)簽綁定:
//各種音效
var flysound; //飛翔的聲音
var scoresound; //得分的聲音
var hitsound; //撞到管道的聲音
var deadsound; //死亡的聲音
var swooshingsound; //切換界面時(shí)的聲音
function init(){flysound = document.getElementById('flysound');scoresound = document.getElementById('scoresound');hitsound = document.getElementById('hitsound');deadsound = document.getElementById('deadsound');swooshingsound = document.getElementById('swooshingsound');
}再定義用來(lái)播放音效的函數(shù) function playSound(sound,src){if(src!='' && typeof src!=undefined){sound.src = src;}
}函數(shù)的兩個(gè)參數(shù)分別指定了要使用的標(biāo)簽和聲音文件的路徑,接下來(lái)僅僅要在須要播放音效的地方調(diào)用這個(gè)函數(shù)并指定聲音文件即可了。比方 else if(gamestate==1){playSound(flysound,"sounds/wing.mp3");birdvy=-jumpvelocity;}這里在點(diǎn)擊鍵盤(pán)按鍵且游戲正在執(zhí)行的時(shí)候使鳥(niǎo)跳躍,并播放扇動(dòng)翅膀的音效。使用的地方非常多,這里不一一提到,用到的五種音效各自是界面切換、扇動(dòng)翅膀、撞上管道、鳥(niǎo)死亡、得分。
<html>
<head>
<title>My flappy bird</title>
<script>
//====================================================
// Name: flappybird_3.html
// Des: flappy bird 的終于版本號(hào)。在第二版的基礎(chǔ)上加入了鳥(niǎo)的上下俯仰動(dòng)作,
// 加入了飛翔得分碰撞等音效,重構(gòu)了部分代碼
// 2014年 4月26日 Create by 風(fēng)小銳
// 2015年 4月30日 modify by 風(fēng)小銳
// 1.改動(dòng)了checkBird方法中關(guān)于得分的推斷,如今不會(huì)在撞上管道左邊的情況下得分了。
// 2.將checkBird方法中關(guān)于得分的推斷放在了碰撞檢測(cè)之前,如今不會(huì)出現(xiàn)最高分比當(dāng)前得分高一分的情況了。
//====================================================
var boxx=0;
var boxy=0;
var boxwidth=384;
var boxheight=512;
var backgroundwidth=384;
var backgroundheight=448;
var groundwidth=18.5;
var groundheight=64;var birdwidth=46;
var birdheight=32;
var birdx=192-birdwidth;
var birdy=224-birdheight;
var birdvy=0; //鳥(niǎo)初始的y軸速度
var birdimage;
var gravity=1; //重力加速度
var jumpvelocity=11; //跳躍時(shí)獲得的向上速度
var birdstate;var upbackground;
var bottombackground;
var bottomstate;
var pipeupimage;
var pipedownimage;
var pipewidth=69; //管道的寬度
var blankwidth=126; //上下管道之間的間隔
var pipeinterval=pipewidth+120; //兩個(gè)管道之間的間隔
var pipenumber=0; //當(dāng)前已經(jīng)讀取管道高度的個(gè)數(shù)
var fps=30; //游戲的幀數(shù)。推薦在30~60之間
var gamestate=0; //游戲狀態(tài):0--未開(kāi)始。1--已開(kāi)始。2--已結(jié)束
var times; //地板圖片的條數(shù) Math.ceil(boxwidth/groundwidth)+1;
var highscore=0; //得到過(guò)的最高分
var score=0 //眼下得到的分?jǐn)?shù)
var movespeed=groundwidth/4; //場(chǎng)景向左移動(dòng)的速度,為底部場(chǎng)景的寬度的1/4var tipimage; //開(kāi)始的提示圖片
var tipwidth=168;
var tipheight=136;var boardimage; //分?jǐn)?shù)板的圖片
var boardx;
var boardy=140;
var boardwidth=282;
var boardheight=245;var canvas;
var ctx;
var i;
var pipeheight=[];
//各種音效
var flysound; //飛翔的聲音
var scoresound; //得分的聲音
var hitsound; //撞到管道的聲音
var deadsound; //死亡的聲音
var swooshingsound; //切換界面時(shí)的聲音var pipeoncanvas=[ //要顯示在Canvas上的管道的location和height[0,0],[0,0],[0,0]];function init(){ctx=document.getElementById('canvas').getContext('2d'); flysound = document.getElementById('flysound');scoresound = document.getElementById('scoresound');hitsound = document.getElementById('hitsound');deadsound = document.getElementById('deadsound');swooshingsound = document.getElementById('swooshingsound');ctx.lineWidth=2;//ctx.font="bold 40px HarlemNights"; //設(shè)置繪制分?jǐn)?shù)的字體 Quartz Regular \HarlemNightsctx.font="bold 40px HirakakuProN-W6"; //繪制字體還原ctx.fillStyle="#FFFFFF";upbackground=new Image();upbackground.src="images/background.png";bottombackground=new Image();bottombackground.src="images/ground.png";bottomstate=1;birdimage=new Image();birdimage.src="images/bird.png";birdstate=1;tipimage=new Image();tipimage.src="images/space_tip.png";boardimage=new Image();boardimage.src="images/scoreboard.png";boardx=(backgroundwidth-boardwidth)/2;///pipeupimage=new Image();pipeupimage.src="images/pipeup.png";pipedownimage=new Image();pipedownimage.src="images/pipedown.png";/times=Math.ceil(boxwidth/groundwidth)+1;initPipe();canvas=document.getElementById("canvas");canvas.addEventListener("mousedown",mouseDown,false);window.addEventListener("keydown",keyDown,false);//window.addEventListener("keydown",getkeyAndMove,false);setInterval(run,1000/fps);
}//隨機(jī)生成管道高度數(shù)據(jù)
function initPipe(){for(i=0;i<200;i++)pipeheight[i]=Math.ceil(Math.random()*216)+56;//高度范圍從56~272for(i=0;i<3;i++){ pipeoncanvas[i][0]=boxwidth+i*pipeinterval;pipeoncanvas[i][1]=pipeheight[pipenumber];pipenumber++;}
}//游戲的主要邏輯及繪制
function run(){//游戲未開(kāi)始if(gamestate==0){drawBeginScene(); //繪制開(kāi)始場(chǎng)景drawBird(); //繪制鳥(niǎo)drawTip(); //繪制提示}//游戲進(jìn)行中if(gamestate==1){birdvy=birdvy+gravity;drawScene(); //繪制場(chǎng)景drawBird(); //繪制鳥(niǎo)drawScore(); //繪制分?jǐn)?shù)checkBird(); //檢測(cè)鳥(niǎo)是否與物體發(fā)生碰撞}//游戲結(jié)束if(gamestate==2){if(birdy+birdheight<backgroundheight) //假設(shè)鳥(niǎo)沒(méi)有落地birdvy=birdvy+gravity;else {birdvy=0;birdy=backgroundheight-birdheight;}drawEndScene(); //繪制結(jié)束場(chǎng)景drawBird(); //繪制鳥(niǎo)drawScoreBoard(); //繪制分?jǐn)?shù)板//ctx.fillRect(boardx+14,boardy+boardheight-40,75,40); // 測(cè)試又一次開(kāi)始button的位置}
}function drawTip(){ctx.drawImage(tipimage,birdx-57,birdy+birdheight+10,tipwidth,tipheight);
}//繪制分?jǐn)?shù)板
function drawScoreBoard(){//繪制分?jǐn)?shù)板ctx.drawImage(boardimage,boardx,boardy,boardwidth,boardheight); //繪制當(dāng)前的得分ctx.fillText(score,boardx+140,boardheight/2+boardy-8);//132//繪制最高分ctx.fillText(highscore,boardx+140,boardheight/2+boardy+44);//184
}
//繪制開(kāi)始場(chǎng)景(不包含管道)
function drawBeginScene(){//清理畫(huà)布上上一楨的畫(huà)面ctx.clearRect(boxx,boxy,boxwidth,boxheight);//繪制上方靜態(tài)背景ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight);//繪制下方的動(dòng)態(tài)背景drawmovingscene();//繪制邊框線ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2);
}//繪制場(chǎng)景
function drawScene(){ctx.clearRect(boxx,boxy,boxwidth,boxheight); //清理畫(huà)布上上一楨的畫(huà)面ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight); //繪制上方靜態(tài)背景drawmovingscene(); //繪制下方的動(dòng)態(tài)背景drawAllPipe(); //繪制管道ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2); //繪制邊框線
}//繪制結(jié)束場(chǎng)景(不包含管道)
function drawEndScene(){ctx.clearRect(boxx,boxy,boxwidth,boxheight); //清理畫(huà)布上上一楨的畫(huà)面ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight); //繪制上方靜態(tài)背景//繪制下方的靜態(tài)背景。依據(jù)bottomstate來(lái)推斷怎樣繪制靜態(tài)地面switch(bottomstate){case 1:for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.75),backgroundheight,groundwidth,groundheight);break;case 2:for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*i,backgroundheight,groundwidth,groundheight);break;case 3:for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.25),backgroundheight,groundwidth,groundheight);break;case 4:for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.5),backgroundheight,groundwidth,groundheight);}//繪制當(dāng)前的柱子for(i=0;i<3;i++){drawPipe(pipeoncanvas[i][0],pipeoncanvas[i][1]);}ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2); //繪制邊框線
}//繪制下方的動(dòng)態(tài)背景
function drawmovingscene(){if(bottomstate==1){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*i,backgroundheight,groundwidth,groundheight);bottomstate=2;}else if(bottomstate==2){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.25),backgroundheight,groundwidth,groundheight);bottomstate=3;}else if(bottomstate==3){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.5),backgroundheight,groundwidth,groundheight);bottomstate=4;}else if(bottomstate==4){for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*(i-0.75),backgroundheight,groundwidth,groundheight);bottomstate=1;}
}//使用給定的高度和位置繪制上下兩根管道
function drawPipe(location,height){//繪制下方的管道ctx.drawImage(pipeupimage,0,0,pipewidth*2,height*2,location,boxheight-(height+groundheight),pipewidth,height);//繪制上方的管道ctx.drawImage(pipedownimage,0,793-(backgroundheight-height-blankwidth)*2,pipewidth*2,(backgroundheight-height-blankwidth)*2,location,0,pipewidth,backgroundheight-height-blankwidth);
}//繪制須要顯示的管道
function drawAllPipe(){for(i=0;i<3;i++){pipeoncanvas[i][0]=pipeoncanvas[i][0]-movespeed;}if(pipeoncanvas[0][0]<=-pipewidth){pipeoncanvas[0][0]=pipeoncanvas[1][0];pipeoncanvas[0][1]=pipeoncanvas[1][1];pipeoncanvas[1][0]=pipeoncanvas[2][0];pipeoncanvas[1][1]=pipeoncanvas[2][1];pipeoncanvas[2][0]=pipeoncanvas[2][0]+pipeinterval;pipeoncanvas[2][1]=pipeheight[pipenumber];pipenumber++;}for(i=0;i<3;i++){drawPipe(pipeoncanvas[i][0],pipeoncanvas[i][1]);}
}function drawBird(){birdy=birdy+birdvy;if(gamestate==0){drawMovingBird();}//依據(jù)鳥(niǎo)的y軸速度來(lái)推斷鳥(niǎo)的朝向,僅僅在游戲進(jìn)行階段生效else if(gamestate==1){ctx.save();if(birdvy<=8){ctx.translate(birdx+birdwidth/2,birdy+birdheight/2);ctx.rotate(-Math.PI/6);ctx.translate(-birdx-birdwidth/2,-birdy-birdheight/2); }if(birdvy>8&&birdvy<=12){ctx.translate(birdx+birdwidth/2,birdy+birdheight/2);ctx.rotate(Math.PI/6);ctx.translate(-birdx-birdwidth/2,-birdy-birdheight/2); }if(birdvy>12&&birdvy<=16){ctx.translate(birdx+birdwidth/2,birdy+birdheight/2);ctx.rotate(Math.PI/3);ctx.translate(-birdx-birdwidth/2,-birdy-birdheight/2); }if(birdvy>16){ctx.translate(birdx+birdwidth/2,birdy+birdheight/2);ctx.rotate(Math.PI/2);ctx.translate(-birdx-birdwidth/2,-birdy-birdheight/2); }drawMovingBird();ctx.restore();}//游戲結(jié)束后鳥(niǎo)頭向下并停止活動(dòng)else if(gamestate==2){ctx.save();ctx.translate(birdx+birdwidth/2,birdy+birdheight/2);ctx.rotate(Math.PI/2);ctx.translate(-birdx-birdwidth/2,-birdy-birdheight/2); ctx.drawImage(birdimage,0,0,92,64,birdx,birdy,birdwidth,birdheight);ctx.restore();}
}
//繪制扇動(dòng)翅膀的鳥(niǎo)
function drawMovingBird(){if(birdstate==1||birdstate==2||birdstate==3){ctx.drawImage(birdimage,0,0,92,64,birdx,birdy,birdwidth,birdheight);birdstate++;}else if(birdstate==4||birdstate==5||birdstate==6){ctx.drawImage(birdimage,92,0,92,64,birdx,birdy,birdwidth,birdheight);birdstate++;}else if(birdstate==7||birdstate==8||birdstate==9){ctx.drawImage(birdimage,184,0,92,64,birdx,birdy,birdwidth,birdheight);birdstate++;if(birdstate==9) birdstate=1;}
}function drawScore(){ctx.fillText(score,boxwidth/2-2,120);
}//檢查鳥(niǎo)是否與管道產(chǎn)生碰撞(不可能與第三組管道重合),以及鳥(niǎo)是否碰撞地面
function checkBird(){//通過(guò)了一根管道加一分if(birdx>pipeoncanvas[0][0]&&birdx<pipeoncanvas[0][0]+movespeed||birdx>pipeoncanvas[1][0]&&birdx<pipeoncanvas[1][0]+movespeed){playSound(scoresound,"sounds/point.mp3");score++;}//先推斷第一組管道//假設(shè)鳥(niǎo)在x軸上與第一組管道重合if(birdx+birdwidth>pipeoncanvas[0][0]&&birdx+birdwidth<pipeoncanvas[0][0]+pipewidth+birdwidth){//假設(shè)鳥(niǎo)在y軸上與第一組管道上部或下部重合if(birdy<backgroundheight-pipeoncanvas[0][1]-blankwidth||birdy+birdheight>backgroundheight-pipeoncanvas[0][1]){hitPipe();}}//推斷第二組管道//假設(shè)鳥(niǎo)在x軸上與第二組管道重合//這里我原本使用else if出現(xiàn)了問(wèn)題,但第一版中卻沒(méi)有問(wèn)題,對(duì)照代碼后發(fā)現(xiàn)原因是上方第一個(gè)if后沒(méi)有加大括號(hào),//這里的else無(wú)法區(qū)分相應(yīng)哪一個(gè)if。加上大括號(hào)后問(wèn)題解決,建議將if后的內(nèi)容都加上大括號(hào),養(yǎng)成良好的變成習(xí)慣else if(birdx+birdwidth>pipeoncanvas[1][0]&&birdx+birdwidth<pipeoncanvas[1][0]+pipewidth+birdwidth){//假設(shè)鳥(niǎo)在y軸上與第二組管道上部或下部重合if(birdy<backgroundheight-pipeoncanvas[1][1]-blankwidth||birdy+birdheight>backgroundheight-pipeoncanvas[1][1]){hitPipe();}}//推斷是否碰撞地面else if(birdy+birdheight>backgroundheight){hitPipe();}
}//撞擊到管道或地面后的一些操作
function hitPipe(){ctx.font="bold 40px HirakakuProN-W6";//ctx.font="bold 35px HarlemNights"; ctx.fillStyle="#000000";playSound(hitsound,"sounds/hit.mp3");playSound(deadsound,"sounds/die.mp3");updateScore();gamestate=2; //游戲結(jié)束
}//刷新最好成績(jī)
function updateScore(){if(score>highscore)highscore=score;
}//處理鍵盤(pán)事件
function keyDown(){if(gamestate==0){playSound(swooshingsound,"sounds/swooshing.mp3");birdvy=-jumpvelocity;gamestate=1;}else if(gamestate==1){playSound(flysound,"sounds/wing.mp3");birdvy=-jumpvelocity;}
}//處理鼠標(biāo)點(diǎn)擊事件,相比鍵盤(pán)多了位置推斷
function mouseDown(ev){var mx; //存儲(chǔ)鼠標(biāo)橫坐標(biāo)var my; //存儲(chǔ)鼠標(biāo)縱坐標(biāo)if ( ev.layerX || ev.layerX == 0) { // Firefoxmx= ev.layerX;my = ev.layerY;} else if (ev.offsetX || ev.offsetX == 0) { // Operamx = ev.offsetX;my = ev.offsetY;}if(gamestate==0){playSound(swooshingsound,"sounds/swooshing.mp3");birdvy=-jumpvelocity;gamestate=1;}else if(gamestate==1){playSound(flysound,"sounds/wing.mp3");birdvy=-jumpvelocity;}//游戲結(jié)束后推斷是否點(diǎn)擊了又一次開(kāi)始else if(gamestate==2){//ctx.fillRect(boardx+14,boardy+boardheight-40,75,40); //鼠標(biāo)是否在又一次開(kāi)始button上if(mx>boardx+14&&mx<boardx+89&&my>boardy+boardheight-40&&my<boardy+boardheight){playSound(swooshingsound,"sounds/swooshing.mp3");restart();}}
}function restart(){gamestate=0; //回到未開(kāi)始狀態(tài)//ctx.font="bold 40px HarlemNights"; //繪制字體還原ctx.font="bold 40px HirakakuProN-W6"; //繪制字體還原ctx.fillStyle="#FFFFFF";score=0; //當(dāng)前分?jǐn)?shù)清零pipenumber=0; //讀取的管道數(shù)清零initPipe(); //又一次初始化水管高度birdx=192-birdwidth; //鳥(niǎo)的位置和速度回到初始值birdy=224-birdheight;birdvy=0;
}function playSound(sound,src){if(src!='' && typeof src!=undefined){sound.src = src;}
}</script>
</head>
<body onLoad="init();">
<audio id="flysound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="scoresound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="hitsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="deadsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<audio id="swooshingsound" playcount="1" autoplay="true" src="">
Your browser doesn't support the HTML5 element audio.
</audio>
<canvas id="canvas" width="384" height="512" style="margin-top: 8px;">
Your browser doesn't support the HTML5 element canvas.
</canvas>
</body>
</html>