FlappyBirdjavascript
遊戲介紹:鼠標點擊開始遊戲,並控制小鳥的飛翔,躲避障礙物,飛向終點。html
HTML代碼以下:java
<html> <head> <meta charset="utf-8"> <title>Flappy Bird</title> </head> <body> <canvas id="canvas" width="340" height="453" style="border: 2px solid #000;background: #fff;"></canvas> <script src="js/bird.js" type="text/javascript"></script> </body> </html>```
JavaScript代碼以下:canvas
var canvas = document.getElementById("canvas"); var c = canvas.getContext("2d"); //三個類,Bird類,Obstacle類,FlappyBird類(遊戲主要函數) function Bird(x, y, image){ this.x = x; this.y = y; this.width = image.width / 2; this.height = image.height; this.image = image; this.draw = function(context, state){ if(state === "up") context.drawImage(image, 0, 0, this.width, this.height, this.x, this.y, this.width, this.height); else context.drawImage(image, this.width, 0, this.width, this.height, this.x, this.y, this.width, this.height); } }; function Obstacle(x, y, h, image){ this.x = x; this.y = y; this.width = image.width / 2; this.height = h; this.flypast = false;//沒被飛過 this.draw = function(context, state){ if(state === "up") context.drawImage(image, 0, 0, this.width, this.height, this.x, this.y, this.width, this.height); else context.drawImage(image, this.width, image.height - this.height, this.width, this.height, this.x, this.y, this.width, this.height); } }; //FlappyBird類包括了遊戲主要參數及運行時須要的函數 function FlappyBird(){} FlappyBird.prototype = { bird: null, //小鳥 bg: null, //背景圖 obs: null, //障礙物 obsList: [], mapWidth: 340, //畫布寬度 mapHeight: 453, //畫布高度 startX: 90, //起始位置 startY: 225, obsDistance: 150, //上下障礙物距離 obsSpeed: 2, //障礙物移動速度 obsInterval: 2000, //製造障礙物間隔ms upSpeed: 8, //上升速度 downSpeed: 3, //降低速度 line: 56, //地面高度 score: 0, //得分 touch: false, //是否觸摸 gameOver: false, /*變化參數能夠改變遊戲難度。 函數列表: CreateMap: function(){} CreateObs: function(){} DrawObs: function(){} CountScore: function(){} ShowScore: function(){} CanMove: function(){} CheckTouch: function(){} ClearScreen: function(){} ShowOver: function(){} */ CreateMap: function(){ //背景 this.bg = new Image(); this.bg.src = "images/flappybird/bg.png"; var startBg = new Image(); startBg.src = "images/flappybird/start.jpg"; // 因爲Image異步加載,在加載完成時繪製圖像 startBg.onload = function(){ c.drawImage(startBg, 0, 0); }; //小鳥 var image = new Image(); image.src = "images/flappybird/bird.png"; image.onload = function(){ this.bird = new Bird(this.startX, this.startY, image); //this.bird.draw(c, "down"); }.bind(this); //障礙物 this.obs = new Image(); this.obs.src = "images/flappybird/obs.png"; this.obs.onload = function(){ var h =100; //默認第一障礙物上管道高度爲100 var h2 = this.mapHeight - h - this.obsDistance; var obs1 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line, this.obs); var obs2 = new Obstacle(this.mapWidth,this.mapHeight-h2,h2-this.line,this.obs); this.obsList.push(obs1); this.obsList.push(obs2); }.bind(this) }, CreateObs: function(){ //隨機產生障礙物上管道高度 var h = Math.floor(Math.random() * (this.mapHeight - this.obsDistance - this.line)); var h2 = this.mapHeight - h - this.obsDistance; var obs1 = new Obstacle(this.mapWidth, 0, h, this.obs); var obs2 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line,this.obs); this.obsList.push(obs1); this.obsList.push(obs2); //移除越界障礙物 if(this.obsList[0].x < -this.obsList[0].width) this.obsList.splice(0, 2); }, DrawObs: function(){ //繪製障礙物 c.fillStyle = "#00ff00"; for(var i = 0;i < this.obsList.length; i++){ this.obsList[i].x -= this.obsSpeed; if(i % 2) this.obsList[i].draw(c, "up"); else this.obsList[i].draw(c, "down"); } }, CountScore: function(){//計分 if(this.obsList[0].x + this.obsList[0].width < this.startX && this.obsList[0].flypast==false){ //小鳥座標超過obsList[0]障礙物 this.score += 1; this.obsList[0].flypast = true; } }, ShowScore: function(){//顯示分數 c.strokeStyle = "#000"; c.lineWidth = 1; c.fillStyle = "#fff"; c.fillText(this.score, 10, 50); c.strokeText(this.score, 10, 50); }, CanMove: function(){//碰撞檢測 if(this.bird.y < 0 || this.bird.y > this.mapHeight - this.bird.height - this.line){ this.gameOver = true; }else{ var boundary = [{ x: this.bird.x, y: this.bird.y },{ x: this.bird.x + this.bird.width, y: this.bird.y },{ x: this.bird.x, y: this.bird.y + this.bird.width, },{ x: this.bird.x + this.bird.width, y: this.bird.y + this.bird.height }]; for(var i = 0; i < this.obsList.length; i++){ for(var j = 0; j < 4; j++) if(boundary[j].x >= this.obsList[i].x && boundary[j].x <= this.obsList[i].x+this.obsList[i].width && boundary[j].y>=this.obsList[i].y && boundary[j].y <= this.obsList[i].y + this.obsList[i].height) { this.gameOver = true; break; } if(this.gameOver) break; } } }, CheckTouch: function(){ if(this.touch){ this.bird.y -= this.upSpeed; this.bird.draw(c, "up") }else{ this.bird.y += this.downSpeed; this.bird.draw(c, "down") } }, ClearScreen: function(){ c.drawImage(this.bg, 0, 0); }, ShowOver: function(){ var overImag = new Image(); overImag.src = "images/flappybird/over.png"; overImag.onload = function(){ c.drawImage(overImag, (this.mapWidth - overImag.width) / 2, (this.mapHeight - overImag.height) / 2 - 50); }.bind(this); return; } }; var game = new FlappyBird(); var Speed = 20; var IsPlay = false; var GameTime = null; var btn_start; window.onload = InitGame; function InitGame(){ c.font = "3em 微軟雅黑"; game.CreateMap(); canvas.onmousedown = function(){ game.touch = true; } canvas.onmouseup = function(){ game.touch = false; }; canvas.onclick = function(){ if(!IsPlay){ IsPlay = true; GameTime = RunGame(Speed); } } } //遊戲運行函數 function RunGame(speed){ var updateTimer = setInterval(function(){ //若小鳥經過第一個障礙物啓動記分器 game.CanMove(); if(game.gameOver){ game.ShowOver(); clearInterval(updateTimer); return; } game.ClearScreen(); game.DrawObs(); game.CheckTouch(); game.CountScore(); game.ShowScore(); }, speed); var obsTimer = setInterval(function(){ if(game.gameOver){ clearInterval(obsTimer); return; } game.CreateObs(); }, game.obsInterval); }```
結果如圖:瀏覽器
雷電app
遊戲介紹:經典小遊戲,飛機從上向下出現,玩家操控本身的飛機發射激光,破壞敵機,本身的飛機被破壞遊戲結束。dom
代碼以下:異步
<html> <head> <meta charset="utf-8"> <title>飛機大戰</title> </head> <body> <canvas id="myCanvas" width="320" height="480" style="border: solid"> 你的瀏覽器不支持canvas畫布元素,請更新瀏覽器得到演示效果。 </canvas> <div id="message_txt" style="display: block;">飛機大戰</div> <div id="score_txt" style="display: block;">分數:0分</div> <script type="text/javascript"> var canvas=document.getElementById('myCanvas'); var context=canvas.getContext('2d'); document.addEventListener('keydown',onKeydown); //飛機類 var Plan=function(image,x,y,n){ this.image=image; this.x=x; this.y=y; this.originX=x; this.originY=y; this.width=image.width/n; this.height=image.height; this.isCaught=false; this.frm=0; this.dis=0; this.n=n; }; Plan.prototype.getCaught=function(bool){ this.isCaught=bool; if (bool==false){ this.originX=0; this.originY=this.y; } }; Plan.prototype.testPoint=function(x,y){ var betweenX=(x>=this.x)&&(x<=this.x+this.width); var betweenY=(y>=this.y)&&(y<=this.y+this.height); return betweenX&&betweenY; }; Plan.prototype.move=function(dx,dy){ this.x+=dx; this.y+=dy; }; Plan.prototype.Y=function(){ return this.y; }; //不斷下移地畫飛機 Plan.prototype.draw=function(ctx){ ctx.save(); ctx.translate(this.x,this.y); ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height); ctx.restore(); this.y++; this.x=this.originX+20*Math.sin(Math.PI/100*this.y); this.dis++; if(this.dis>=3){//3幀換圖 this.dis=0; this.frm++; if(this.frm>=this.n) this.frm=0; } }; //原地不動畫飛機 Plan.prototype.draw2=function(ctx){ ctx.save(); ctx.translate(this.x,this.y); ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height); ctx.restore(); this.dis++; if(this.dis>=3){//3幀換圖 this.dis=0; this.frm++; if(this.frm>=this.n) this.frm=0; } }; //飛機碰撞檢測 //將全部子彈對象的矩形區域與敵機對象的矩形區域逐一檢測,若是重疊則說明子彈與與敵機的碰撞 Plan.prototype.hitTestObject=function(planobj){ if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height)) //發生碰撞 return true; else return false; } function iscolliding(ax,ay,aw,ah,bx,by,bw,bh){ if(ay>by+bh||by>ay+ah||ax>bx+bw||bx>ax+aw) return false; else return true; } //子彈類 var Bullet=function(image,x,y){ this.image=image; this.x=x; this.y=y; this.originX=x; this.originY=y; this.width=image.width/4; this.height=image.height; this.isCaught=false; this.frm=0; this.dis=0; } Bullet.prototype.testPoint=function(x,y){ var betweenX=(x>=this.x)&&(x<this.x+this.width); var betweenY=(y>=this.y)&&(y<this.y+this.height); return betweenX&&betweenY; }; Bullet.prototype.move=function(dx,dy){ this.x+=dx; this.y+=dy; }; Bullet.prototype.Y=function(){ return this.y; }; Bullet.prototype.draw=function(ctx){ ctx.save(); ctx.translate(this.x,this.y); ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height); ctx.restore(); this.y--; this.dis++; if(this.dis>=10){//10幀換圖 this.dis=0; this.frm++; if(this.frm>=4) this.frm=0; } }; //檢測子彈與敵人的碰撞 Bullet.prototype.hitTestObject=function(planobj){ if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height)) return true; else return false; } //爆炸動畫 var Bomb=function(image,x,y){ this.image=image; this.x=x; this.y=y; this.width=image.width/6; this.height=image.height; this.frm=0; this.dis=0; }; Bomb.prototype.draw2=function(ctx){ ctx.save(); ctx.translate(this.x,this.y); if(this.frm>=6) return ; ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height); ctx.restore(); this.dis++; if(this.dis>=10){//10幀換圖 this.dis=0; this.frm++; } }; var plan1,plan2,plan3,plan4,caughtplan=null; var isClick=false; var mouseX,mouseY,preX,preY; var plans=[]; var bullets=[]; var bombs=[]; var score=0; var overflag=false;//遊戲是否結束,true爲結束 var myplane;//己方飛機 //導入圖片 var image=new Image(); var image2=new Image(); var image3=new Image(); var image4=new Image(); var image5=new Image(); var bakground=new Image(); bakground.src='images/map_0.png'; image.src='images/plan.png';//本身飛機圖片 image.onload=function(){ } image2.src='images/bomb.png';//爆炸圖片 image2.onload=function(){ } image3.src='images/enemy.png';//敵機圖片 image3.onload=function(){ myplane=new Plan(image,300*Math.random(),400,6); plan_interval=setInterval(function(){ plans.push(new Plan(image3,300*Math.random(),20*Math.random(),2)); },3000);//3秒產生一架敵機 setInterval(function(){ context.clearRect(0,0,320,480); context.drawImage(bakground,0,0); //畫己方飛機 if(!overflag)//遊戲沒有結束 myplane.draw2(context);//原地不動 //畫敵方飛機 for(var i=plans.length-1;i>=0;i--){ if (plans[i].Y()>400) plans.splice(i,1);//刪除敵機 else plans[i].draw(context); } //畫子彈 for (var i=bullets.length-1;i>=0;i--){ if (bullets[i].Y()<100) bullets.splice(i,1);//刪除子彈 else bullets[i].draw(context); } //碰撞檢測 //判斷敵機碰到玩家本身飛機 for (vari=plans.length-1;i>=0;i--){ e1=plans[i]; if(e1!=null && myplane!=null && myplane.hitTestObject(e1)){ clearInterval(plan_interval);//清除定時器,再也不產生敵機 plans.splice(i,1);//刪除敵機 bombs.push(new Bomb(image2,myplane.x,myplane.y)); message_txt.innerHTML='敵機碰到玩家本身飛機,遊戲結束'; overflag=true; } } //判斷子彈碰到敵機 for(var j=bullets.length-1;j>=0;j--){ var b1=bullets[j]; for(var i=plans.length-1;i>=0;i--){ e1=plans[i]; if (e1!=null && b1!=null && b1.hitTestObject(e1)){//擊中敵機 plans.splice(i,1);//刪除敵機 bullets.splice(i,1);//刪除此顆子彈 bombs.push(new Bomb(image2,b1.x,b1.y-36)); message_txt.innerHTML='敵機被擊中,加20分'; score+=20; score_txt.innerHTML='分數:'+score+'分'; } } } //畫爆炸 for (var i=bombs.length-1;i>=0;i--){ if (bombs[i].frm>=6) bombs.splice(i,1);//刪除炸彈 else bombs[i].draw2(context); } },1000/60); }; image4.src='images/bullet.png';//子彈圖片 image4.onload=function(){ }; //飛機移動控制 function onKeydown(e){ if(e.keyCode==32){//空格 //發射子彈 bullets.push(new Bullet(image4,myplane.x,myplane.y-36)); }else if(e.keyCode==37){//向左 myplane.move(-10,0); }else if(e.keyCode==39){//向右 myplane.move(10,0); }else if(e.keyCode==38){//向上 myplane.move(0,-10); }else if(e.keyCode==40){//向下 myplane.move(0,10); } } </script> </body> </html>```
結果截圖:函數