<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標簽的設定,用于繪制圖像。
var fps=30; //游戲的幀數,推薦在30~60之間
function init(){ctx=document.getElementById('canvas').getContext('2d'); ctx.lineWidth=2;canvas=document.getElementById("canvas");setInterval(run,1000/fps);
}游戲主邏輯run()將會以每秒fps幀的速度執行,這和后面繪制移動物體有關。
另一些全局變量的設置,詳細含義后面還會提到 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; //鳥初始的y軸速度
var gravity=1; //重力加速度
var jumpvelocity=11; //跳躍時獲得的向上速度
var pipewidth=69; //管道的寬度
var blankwidth=126; //上下管道之間的間隔
var pipeinterval=pipewidth+120; //兩個管道之間的間隔
var birdstate;
var upbackground;
var bottombackground;
var birdimage;
var pipeupimage;
var pipedownimage;
var pipenumber=0; //當前已經讀取管道高度的個數
var fps=30; //游戲的幀數,推薦在30~60之間
var gamestate=1; //游戲狀態:0--未開始,1--已開始。2--已結束
var times;
var canvas;
var ctx;
var i;
var bottomstate;
var pipeheight=[];
var pipeoncanvas=[ //要顯示在Canvas上的管道的location和height[0,0],[0,0],[0,0]];
二、游戲基本場景的繪制
游戲中的基本場景包含上方精巧的背景,下方移動地面的繪制,以及管道的繪制。
首先是精巧的圖片,僅僅要用Image對象保存圖片地址后使用drawImage指定位置和大小即可了。
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);
}下方動態的地面較為復雜,先貼出代碼 //繪制下方的動態背景
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;}
}我這里找到的地面圖片是這個樣子的。因此想要繪制以下的完整地須要先計算出多少條能將下部填滿,使用了 for(i=0;i<times;i++)ctx.drawImage(bottombackground,groundwidth*i,backgroundheight,groundwidth,groundheight);就繪制出了下方地面的一幀圖像,想要讓地面動起來,我選擇每一幀都讓繪制的圖片向左移動1/4寬度,這樣就能夠在游戲執行時顯示地面在移動。這里使用了一個bottomstate狀態量,以此來記錄當前地面的繪制狀態,每次加1。到4后下一幀變為1。
//隨機生成管道高度數據
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++;}
}鑒于管道在畫面中不會同一時候出現4個,因此我首先取三個管道高度數據放入pipecanvas數組,并依據畫面的寬度和管道的間隔生成管道位置,為繪制管道作準備,這是pipecanvas的結構 var pipeoncanvas=[ //要顯示在Canvas上的管道的location和height[0,0],[0,0],[0,0]];
以下就要對管道進行繪制了,先實現一根管道上下兩部分的繪制
//使用給定的高度和位置繪制上下兩根管道
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);
}函數比較簡單不再贅述,在run函數中增加drawAllPipe函數。來繪制要顯示的三根管道 //繪制須要顯示的管道
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]);}
}這里會先推斷第一根管道是否已經移出畫布,假設移出了畫布則后面的管道數據向前順延,并將新的管道高度讀入第三根管道,處理完后按順序意思繪制三根管道。
var highscore=0; //得到過的最高分
var score=0 //眼下得到的分數//通過了一根管道加一分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"; //設置繪制分數的字體 ctx.fillStyle="#FFFFFF";開始時的提示和結束的計分板都是普通的圖片,計分板上用兩個文本繪制了當前分數和得到的最高分數 function drawTip(){ctx.drawImage(tipimage,birdx-57,birdy+birdheight+10,tipwidth,tipheight);
}//繪制分數板
function drawScoreBoard(){//繪制分數板ctx.drawImage(boardimage,boardx,boardy,boardwidth,boardheight); //繪制當前的得分ctx.fillText(score,boardx+140,boardheight/2+boardy-8);//132//繪制最高分ctx.fillText(highscore,boardx+140,boardheight/2+boardy+44);//184
}這里的最高分highscroe會在每次游戲結束時更新 //刷新最好成績
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>為了時播放音效時不發生沖突,我為每一個音效定義了一個audio標簽,這樣在使用中就不會出現故障。
然后將定義的變量與標簽綁定:
//各種音效
var flysound; //飛翔的聲音
var scoresound; //得分的聲音
var hitsound; //撞到管道的聲音
var deadsound; //死亡的聲音
var swooshingsound; //切換界面時的聲音
function init(){flysound = document.getElementById('flysound');scoresound = document.getElementById('scoresound');hitsound = document.getElementById('hitsound');deadsound = document.getElementById('deadsound');swooshingsound = document.getElementById('swooshingsound');
}再定義用來播放音效的函數 function playSound(sound,src){if(src!='' && typeof src!=undefined){sound.src = src;}
}函數的兩個參數分別指定了要使用的標簽和聲音文件的路徑,接下來僅僅要在須要播放音效的地方調用這個函數并指定聲音文件即可了。比方 else if(gamestate==1){playSound(flysound,"sounds/wing.mp3");birdvy=-jumpvelocity;}這里在點擊鍵盤按鍵且游戲正在執行的時候使鳥跳躍,并播放扇動翅膀的音效。使用的地方非常多,這里不一一提到,用到的五種音效各自是界面切換、扇動翅膀、撞上管道、鳥死亡、得分。
<html>
<head>
<title>My flappy bird</title>
<script>
//====================================================
// Name: flappybird_3.html
// Des: flappy bird 的終于版本號。在第二版的基礎上加入了鳥的上下俯仰動作,
// 加入了飛翔得分碰撞等音效,重構了部分代碼
// 2014年 4月26日 Create by 風小銳
// 2015年 4月30日 modify by 風小銳
// 1.改動了checkBird方法中關于得分的推斷,如今不會在撞上管道左邊的情況下得分了。
// 2.將checkBird方法中關于得分的推斷放在了碰撞檢測之前,如今不會出現最高分比當前得分高一分的情況了。
//====================================================
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; //鳥初始的y軸速度
var birdimage;
var gravity=1; //重力加速度
var jumpvelocity=11; //跳躍時獲得的向上速度
var birdstate;var upbackground;
var bottombackground;
var bottomstate;
var pipeupimage;
var pipedownimage;
var pipewidth=69; //管道的寬度
var blankwidth=126; //上下管道之間的間隔
var pipeinterval=pipewidth+120; //兩個管道之間的間隔
var pipenumber=0; //當前已經讀取管道高度的個數
var fps=30; //游戲的幀數。推薦在30~60之間
var gamestate=0; //游戲狀態:0--未開始。1--已開始。2--已結束
var times; //地板圖片的條數 Math.ceil(boxwidth/groundwidth)+1;
var highscore=0; //得到過的最高分
var score=0 //眼下得到的分數
var movespeed=groundwidth/4; //場景向左移動的速度,為底部場景的寬度的1/4var tipimage; //開始的提示圖片
var tipwidth=168;
var tipheight=136;var boardimage; //分數板的圖片
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; //切換界面時的聲音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"; //設置繪制分數的字體 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);
}//隨機生成管道高度數據
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(){//游戲未開始if(gamestate==0){drawBeginScene(); //繪制開始場景drawBird(); //繪制鳥drawTip(); //繪制提示}//游戲進行中if(gamestate==1){birdvy=birdvy+gravity;drawScene(); //繪制場景drawBird(); //繪制鳥drawScore(); //繪制分數checkBird(); //檢測鳥是否與物體發生碰撞}//游戲結束if(gamestate==2){if(birdy+birdheight<backgroundheight) //假設鳥沒有落地birdvy=birdvy+gravity;else {birdvy=0;birdy=backgroundheight-birdheight;}drawEndScene(); //繪制結束場景drawBird(); //繪制鳥drawScoreBoard(); //繪制分數板//ctx.fillRect(boardx+14,boardy+boardheight-40,75,40); // 測試又一次開始button的位置}
}function drawTip(){ctx.drawImage(tipimage,birdx-57,birdy+birdheight+10,tipwidth,tipheight);
}//繪制分數板
function drawScoreBoard(){//繪制分數板ctx.drawImage(boardimage,boardx,boardy,boardwidth,boardheight); //繪制當前的得分ctx.fillText(score,boardx+140,boardheight/2+boardy-8);//132//繪制最高分ctx.fillText(highscore,boardx+140,boardheight/2+boardy+44);//184
}
//繪制開始場景(不包含管道)
function drawBeginScene(){//清理畫布上上一楨的畫面ctx.clearRect(boxx,boxy,boxwidth,boxheight);//繪制上方靜態背景ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight);//繪制下方的動態背景drawmovingscene();//繪制邊框線ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2);
}//繪制場景
function drawScene(){ctx.clearRect(boxx,boxy,boxwidth,boxheight); //清理畫布上上一楨的畫面ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight); //繪制上方靜態背景drawmovingscene(); //繪制下方的動態背景drawAllPipe(); //繪制管道ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2); //繪制邊框線
}//繪制結束場景(不包含管道)
function drawEndScene(){ctx.clearRect(boxx,boxy,boxwidth,boxheight); //清理畫布上上一楨的畫面ctx.drawImage(upbackground,0,0,backgroundwidth,backgroundheight); //繪制上方靜態背景//繪制下方的靜態背景。依據bottomstate來推斷怎樣繪制靜態地面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);}//繪制當前的柱子for(i=0;i<3;i++){drawPipe(pipeoncanvas[i][0],pipeoncanvas[i][1]);}ctx.strokeRect(boxx+1,boxy+1,boxwidth-2,boxheight-2); //繪制邊框線
}//繪制下方的動態背景
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();}//依據鳥的y軸速度來推斷鳥的朝向,僅僅在游戲進行階段生效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();}//游戲結束后鳥頭向下并停止活動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();}
}
//繪制扇動翅膀的鳥
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);
}//檢查鳥是否與管道產生碰撞(不可能與第三組管道重合),以及鳥是否碰撞地面
function checkBird(){//通過了一根管道加一分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++;}//先推斷第一組管道//假設鳥在x軸上與第一組管道重合if(birdx+birdwidth>pipeoncanvas[0][0]&&birdx+birdwidth<pipeoncanvas[0][0]+pipewidth+birdwidth){//假設鳥在y軸上與第一組管道上部或下部重合if(birdy<backgroundheight-pipeoncanvas[0][1]-blankwidth||birdy+birdheight>backgroundheight-pipeoncanvas[0][1]){hitPipe();}}//推斷第二組管道//假設鳥在x軸上與第二組管道重合//這里我原本使用else if出現了問題,但第一版中卻沒有問題,對照代碼后發現原因是上方第一個if后沒有加大括號,//這里的else無法區分相應哪一個if。加上大括號后問題解決,建議將if后的內容都加上大括號,養成良好的變成習慣else if(birdx+birdwidth>pipeoncanvas[1][0]&&birdx+birdwidth<pipeoncanvas[1][0]+pipewidth+birdwidth){//假設鳥在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; //游戲結束
}//刷新最好成績
function updateScore(){if(score>highscore)highscore=score;
}//處理鍵盤事件
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;}
}//處理鼠標點擊事件,相比鍵盤多了位置推斷
function mouseDown(ev){var mx; //存儲鼠標橫坐標var my; //存儲鼠標縱坐標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;}//游戲結束后推斷是否點擊了又一次開始else if(gamestate==2){//ctx.fillRect(boardx+14,boardy+boardheight-40,75,40); //鼠標是否在又一次開始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; //回到未開始狀態//ctx.font="bold 40px HarlemNights"; //繪制字體還原ctx.font="bold 40px HirakakuProN-W6"; //繪制字體還原ctx.fillStyle="#FFFFFF";score=0; //當前分數清零pipenumber=0; //讀取的管道數清零initPipe(); //又一次初始化水管高度birdx=192-birdwidth; //鳥的位置和速度回到初始值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>