[Canvas]空战游戏 已经可以玩了 1.13Playable
空战游戏做到这里,己方运动,己方发射子弹,敌方运动,敌方发射子弹,子弹与飞机碰撞,飞机与飞机碰撞都已经具备了,换言之已经可以玩了。
还需要一个奖励升级系统,在上面显示击落敌机数量等,还有己方不幸被击落显示GG等功能。
请点此下载源码,并用Chrome打开玩赏。
图例:
源码:
<!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>飞越河谷的战机1.13 19.3.16 13:36 by:逆火狂飙 horn19782016@163.com</title> <style> *{ margin:1px; padding:1px; } #canvas{ background:#ffffff; } #controls{ float:left; } </style> </head> <body onload="init()"> <table border="0px"> <tr> <td width="50px"valign="top"> <div id="controls"> <input id='animateBtn' type='button' value='运动'/> </div> </td> <td width="100%" align="center"> <canvas id="canvas" width="1200px" height="562px" > 出现文字表示你的浏览器不支持HTML5 </canvas> </td> </tr> </table> </body> </html> <script type="text/javascript"> <!-- var paused=true; animateBtn.onclick=function(e){ paused=! paused; if(paused){ animateBtn.value="运动"; }else{ animateBtn.value="暂停"; window.requestAnimationFrame(animate); } } var ctx; // 绘图环境 var bg; // 背景 var lastTime=0; // 上次时间,用以计算FPS var fps=0; // Frame per second var myPlane; // 己方飞机 var myShellMng; // 己方子弹管理类 var enemyPlaneMng; // 敌方飞机管理者 var explosionMng; // 爆炸管理者 var enemyShellMng; // 敌方子弹管理类 // 初始化,被onload调用 function init(){ // 创建背景对象 bg=new Background(); // 初始化CTX var canvas=document.getElementById('canvas'); canvas.width=bg.width*6; canvas.height=bg.height*4; ctx=canvas.getContext('2d'); // +new Date=new Date().getTime(); lastTime=+new Date; // 创建本机对象 myPlane=new MyPlane(ctx.canvas.width/2,canvas.height-100); // 本机子弹管理者 myShellMng=new MyShellMng(); // 敌机管理者 enemyPlaneMng=new EnemyPlaneMng(); // 爆炸管理者 explosionMng=new ExplosionMng(); // 敌方子弹管理者 enemyShellMng=new EnemyShellMng(); // 响应键盘按下事件 canvas.addEventListener('keydown', doKeyDown, true); window.addEventListener('keydown', doKeyDown, true); // 响应键盘弹起事件 canvas.addEventListener('keyup', doKeyUp, true); window.addEventListener('keyup', doKeyUp, true); canvas.focus(); }; //------------------------------------ // 响应键盘按下事件 //------------------------------------ function doKeyDown(e) { var keyID = e.keyCode ? e.keyCode :e.which; if(keyID === 38 || keyID === 87) { // up arrow and W myPlane.toUp=true; e.preventDefault(); } if(keyID === 40 || keyID === 83) { // down arrow and S myPlane.toDown=true; e.preventDefault(); } if(keyID === 39 || keyID === 68) { // right arrow and D myPlane.toRight=true; e.preventDefault(); } if(keyID === 37 || keyID === 65) { // left arrow and A myPlane.toLeft=true; e.preventDefault(); } if(keyID === 32 ) { // SpaceBar // 按下和弹起必须成对出现,否则画面会僵 myPlane.shoot(); e.preventDefault(); } } //------------------------------------ // 响应键盘弹起事件 //------------------------------------ function doKeyUp(e) { var keyID = e.keyCode ? e.keyCode :e.which; if(keyID === 38 || keyID === 87) { // up arrow and W myPlane.toUp=false; e.preventDefault(); } if(keyID === 40 || keyID === 83) { // down arrow and S myPlane.toDown=false; e.preventDefault(); } if(keyID === 39 || keyID === 68) { // right arrow and D myPlane.toRight=false; e.preventDefault(); } if(keyID === 37 || keyID === 65) { // left arrow and A myPlane.toLeft=false; e.preventDefault(); } if(keyID === 32 ) { // SpaceBar // 按下和弹起必须成对出现,否则画面会僵 e.preventDefault(); } } // 更新各对象状态 function update(){ myPlane.move(); myShellMng.move(); // 判断敌机和本机是否相撞 enemyPlaneMng.isCrashed(myPlane); // 敌机移动 enemyPlaneMng.move(); // 判断本方子弹是否与敌机相撞 myShellMng.probeCrashedEnemyPlane(); // 补充敌机 enemyPlaneMng.reload(); // 移动敌方子弹 enemyShellMng.move(); // 判断敌方子弹是否与本机相撞 enemyShellMng.probeCrashedMyPlane(); } // 在CTX画出各个对象 function draw(){ // 清屏 ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); // 画背景 fps=calculateFps(new Date); bg.setOffset(fps); var bgImg=bg.getImage(); ctx.drawImage(bgImg,0,bg.height-bg.Offset,bg.width,bg.Offset,0,0,ctx.canvas.width,4*bg.Offset); ctx.drawImage(bgImg,0,0,bg.width,bg.height-bg.Offset,0,4*bg.Offset,canvas.width,canvas.height-4*bg.Offset); // 画己方飞机 myPlane.paint(ctx); // 画己方子弹 myShellMng.paint(ctx); // 画敌机 enemyPlaneMng.paint(ctx); // 画爆炸 explosionMng.paint(ctx); // 画敌方子弹 enemyShellMng.paint(ctx); } // 计算FPS function calculateFps(now){ var retval=1000/(now-lastTime); lastTime=now; return retval; } // 播放 function animate(){ if(!paused){ update(); draw(); } window.requestAnimationFrame(animate); } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>点类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Point=function(x,y){ this.x=x; this.y=y; } Point.prototype={ x:0, // 横坐标 y:0, // 纵坐标 } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<点类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>背景类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Background=function(){ this.width=104; this.height=156; this.files=['bgBlue.jpg','bgRiver.jpg','bgSky.jpg','bgVolcano.jpg']; this.Offset=0; this.velocity=40; } Background.prototype={ width:104, // 背景图片原始宽度 height:156, // 背景图片原始高度 files:[], // 图片数组 Offset:0, // 偏移值 velocity:40, // 背景移动速度 loopValue:0, // 循环累加值,用来确定时哪一张图片 getImage:function(){ this.loopValue++; if(this.loopValue>=3999){ this.loopValue=0; } var index=Math.floor(this.loopValue/1000); var img=new Image(); img.src=this.files[index]; return img; }, setOffset:function(fps){ this.Offset=this.Offset<this.height?this.Offset+this.velocity/fps:0; }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<背景类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>我方战机类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MyPlane=function(x,y){ Point.apply(this,arguments); this.types=[ {width:56,height:41,file:'m1.png',shellCount:1,shellSpeed:4,}, {width:56,height:41,file:'m2.png',shellCount:2,shellSpeed:4.5,}, {width:80,height:54,file:'m3.png',shellCount:3,shellSpeed:5,}, {width:109,height:83,file:'m4.png',shellCount:4,shellSpeed:5.5,}, {width:109,height:81,file:'m5.png',shellCount:5,shellSpeed:6,}, {width:109,height:91,file:'m6.png',shellCount:6,shellSpeed:6.5,}, ]; } MyPlane.prototype={ files:[], // 存储图片的数组 step:4, // 每次移动多远 toLeft:false, // 是否向左移动 toRight:false, // 是否向右移动 toUp:false, // 是否向上移动 toDown:false, // 是否向下移动 level:5, // 等级 destroyed:false, // 是否被击毁或撞毁 paint:function(ctx){ if(this.destroyed==false){ var index=this.level; if(index>this.types.length-1){ console.log("非法的本机level值="+this.level); index=this.types.length-1; } var img=new Image(); img.src=this.types[index].file; ctx.drawImage(img,this.x-this.types[index].width/2,this.y-this.types[index].height/2); // 标出this,x,this.y所在位置 //var img2=new Image(); //img2.src="shoot.png"; //ctx.drawImage(img2,this.x-5.5,this.y-5.5); } }, // 得到飞机的左上角 getLeftUpPoint:function(){ var index=this.level; var p=new Point(this.x-this.types[index].width/2,this.y-this.types[index].height/2); return p; }, // 得到飞机的右上角 getRightUpPoint:function(){ var index=this.level; var p=new Point(this.x+this.types[index].width/2,this.y-this.types[index].height/2); return p; }, // 得到飞机的左下角 getLeftDownPoint:function(){ var index=this.level; var p=new Point(this.x-this.types[index].width/2,this.y+this.types[index].height/2); return p; }, // 得到飞机的右下角 getRightDownPoint:function(){ var index=this.level; var p=new Point(this.x+this.types[index].width/2,this.y+this.types[index].height/2); return p; }, move:function(){ // 加入边界判断 2019年3月13日19点16分 var type=this.types[this.level].file; if(this.x<0){ this.x=0; this.toLeft=false; } if(this.x>ctx.canvas.width){ this.x=ctx.canvas.width; this.toRight=false; } if(this.y<0){ this.y=0; this.toUp=false; } if(this.y>ctx.canvas.height){ this.y=ctx.canvas.height; this.toDown=false; } // 运动 if(this.toLeft==true && this.destroyed==false){ this.x-=this.step; } if(this.toRight==true && this.destroyed==false){ this.x+=this.step; } if(this.toUp==true && this.destroyed==false){ this.y-=this.step; } if(this.toDown==true && this.destroyed==false){ this.y+=this.step; } }, // 本机开炮 shoot:function(){ if(this.destroyed==false){ var index=this.level; // 得到炮弹 var shellCount=this.types[index].shellCount; var shells=myShellMng.fetch(shellCount); // 用来控制炮弹发射位置 var xLeft=this.x-this.types[index].width/2; var offset=this.types[index].width/(shellCount+1); for(var i=0;i<shellCount;i++){ var s=shells[i]; s.x=xLeft+(i+1)*offset; s.y=this.y; s.speed=this.types[index].shellSpeed; } } }, // 根据等级取得炮弹数量 /*getShellNum:function(){ if(this.level==0){ return 1; } else if(this.level==1){ return 2; } else if(this.level==2){ return 3; } else if(this.level==3){ return 4; } else if(this.level==4){ return 5; } else if(this.level==5){ return 6; } else if(this.level==6){ return 7; } else if(this.level==7){ return 8; } else{ return 9; } },*/ // 根据等级取得炮弹速度 /*getShellSpeed:function(){ if(this.level==0){ return 2; } else if(this.level==1){ return 2; } else if(this.level==2){ return 4; } else if(this.level==3){ return 4; } else if(this.level==4){ return 5; } else if(this.level==5){ return 5; } else if(this.level==6){ return 6; } else if(this.level==7){ return 7; } else{ return 8; } },*/ // 判断以x,y为坐标的点是否进入本机机四角范围内 isWithinLimits:function(x,y){ var index=this.level; var left=this.x-this.types[index].width/2; var top=this.y-this.types[index].height/2; var width=this.types[index].width; var height=this.types[index].height; if(left<x && x<left+width && top<y && y<top+height){ return true; }else{ return false; } }, // 看地方炮弹是否命中本机 isShooted:function(shell){ if(shell.destroyed==true){ return false; } // 如果炮弹打中本机范围 if(this.isWithinLimits(shell.x,shell.y)){ this.destroyed=true; shell.destroyed=true; // 制造爆炸 explosionMng.fire(this.x,this.y); // 游戏结束 return true; } return false; }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<我方战机类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>我方炮弹类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MyShell=function(x,y){ Point.apply(this,arguments); this.types=[ {width:11,height:11,file:'shell0.png'}, {width:11,height:11,file:'shell1.png'}, {width:11,height:11,file:'shell2.png'}, {width:11,height:11,file:'shell3.png'}, {width:11,height:11,file:'shell4.png'}, {width:11,height:11,file:'shell5.png'}, {width:11,height:11,file:'shell6.png'}, {width:18,height:18,file:'shell7.png'}, ]; } MyShell.prototype={ types:[], // 炮弹型号 destroyed:false,// 是否被敌机撞毁 visible:true, // 是否在CTX显示范围内 level:3, // 等级,用以决定炮弹型号 speed:4, // 炮弹速度(己方炮弹向上飞行) paint:function(ctx){ if(this.visible==false){ return; } if(this.destroyed==false){ // 没被击毁显示炮弹型号 var img=new Image(); var index=this.level; img.src=this.types[index].file; ctx.drawImage(img,this.x-this.types[index].width/2,this.y-this.types[index].height/2); } }, move:function(){ // 设置越界不可见 if(this.x<0){ this.visible=false; } if(this.x>ctx.canvas.width){ this.visible=false; } if(this.y<0){ this.visible=false; } if(this.y>ctx.canvas.height){ this.visible=false; } if(this.visible==true && this.destroyed==false){ this.y-=this.speed; } }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<我方炮弹类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>我方炮弹管理者类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>19.3.16 MyShellMng=function(){ shells=new Array(); } MyShellMng.prototype={ shells:[], // 己方炮弹对象数组 paint:function(ctx){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; s.paint(ctx); } }, // 取出子弹,count为个数 fetch:function(count){ var retval=new Array(); console.log("原有己方炮弹数量=",this.shells.length); // 先取原有的炮弹 for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; if(s.visible==false || s.destroyed==true){ s.destroyed=false; s.visible=true; if(retval.length<count){ retval.push(s); } } } // 不足再创建新的炮弹 while(retval.length<count){ var s=new MyShell(0,0); this.shells.push(s); retval.push(s); } console.log("现有己方炮弹数量=",this.shells.length); return retval; }, // 移动炮弹 move:function(){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; s.move(); } }, // 判断炮弹是否撞到敌机 probeCrashedEnemyPlane:function(){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; if(s.visible==true && s.destroyed==false){ if(enemyPlaneMng.isShooted(s)==true){ s.destroyed=true; return; } } } }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<我方炮弹管理者类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // 常规函数:角度得到弧度 function getRad(degree){ return degree/180*Math.PI; } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>敌方飞机类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> EnemyPlane=function(x,y,level){ Point.apply(this,arguments); this.level=level; this.types=[ {width:117,height:64,file:'e0.png',shellCount:1,shootInterval:300,shellSpeed:3 ,reciprocatingRadius:0}, {width:117,height:64,file:'e1.png',shellCount:2,shootInterval:270,shellSpeed:4 ,reciprocatingRadius:0.5}, {width:100,height:77,file:'e2.png',shellCount:3,shootInterval:240,shellSpeed:5 ,reciprocatingRadius:1}, {width:117,height:85,file:'e3.png',shellCount:4,shootInterval:210,shellSpeed:6 ,reciprocatingRadius:1.5}, {width:117,height:93,file:'e4.png',shellCount:5,shootInterval:180,shellSpeed:7 ,reciprocatingRadius:2}, {width:117,height:93,file:'e5.png',shellCount:6,shootInterval:150,shellSpeed:8 ,reciprocatingRadius:2.25}, {width:117,height:96,file:'e6.png',shellCount:7,shootInterval:120,shellSpeed:9 ,reciprocatingRadius:2.5}, {width:117,height:99,file:'e7.png',shellCount:8,shootInterval:90 ,shellSpeed:10,reciprocatingRadius:2.75}, ]; } EnemyPlane.prototype={ types:[], // 飞机型号数组 destroyed:false, // 是否被击毁 level:7, // 等级,用此取飞机型号 visible:true, // 是否在ctx显示范围内 speed:2, // 敌机向下飞行的速度 paint:function(ctx){ // 不可见则不显示 if(this.visible==false){ return; } if(this.destroyed==false){ // 没被击毁显示飞机型号 var img=new Image(); var index=this.level; if(index>this.types.length-1){ console.log("非法的敌机level值="+this.level); index=this.types.length-1; } img.src=this.types[index].file; ctx.drawImage(img,this.x-this.types[index].width/2,this.y-this.types[index].height/2); // 标出本机下x,y坐标 //var img2=new Image(); //img2.src="shoot.png"; //ctx.drawImage(img2,this.x-5.5,this.y-5.5); } }, // 判断以x,y为坐标的点是否进入敌机四角范围内 isWithinLimits:function(x,y){ var index=this.level; var left=this.x-this.types[index].width/2; var top=this.y-this.types[index].height/2; var width=this.types[index].width; var height=this.types[index].height; if(left<x && x<left+width && top<y && y<top+height){ return true; }else{ return false; } }, // 敌机飞行 move:function(){ // 设置越界不可见 if(this.x<0){ this.visible=false; } if(this.x>ctx.canvas.width){ this.visible=false; } if(this.y<0){ this.visible=false; } if(this.y>ctx.canvas.height){ this.visible=false; } if(this.visible){ var index=this.level; this.y+=this.speed; this.x+=this.types[index].reciprocatingRadius*Math.sin(getRad(this.y)); // 行动中随机开枪 var rnd=this.getRndBetween(0,this.types[index].shootInterval);// 上限越大打得越慢,这个值可以叫ShootInterval if(rnd<1){ this.shoot(); } } }, // 得到随机数 getRndBetween:function (lowerLimit,upperLimit){ return Math.floor(Math.random()*(upperLimit-lowerLimit+1))+lowerLimit; }, // 敌机开炮 shoot:function(){ if(this.destroyed==false){ var index=this.level; // 得到炮弹 var shellCount=this.types[index].shellCount; var shells=enemyShellMng.fetch(shellCount); // 用来控制炮弹发射位置 var xLeft=this.x-this.types[index].width/2; var offset=this.types[index].width/(shellCount+1); for(var i=0;i<shellCount;i++){ var s=shells[i]; s.x=xLeft+(i+1)*offset; s.y=this.y; s.speed=this.types[index].shellSpeed; } } }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<敌方飞机类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>敌方飞机管理类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> EnemyPlaneMng=function(x,y){ Point.apply(this,arguments); this.planes=new Array(); this.planes.push(new EnemyPlane(ctx.canvas.width/2,20,0)); //this.planes.push(new EnemyPlane(ctx.canvas.width/2-80,20,1)); //this.planes.push(new EnemyPlane(ctx.canvas.width/2+80,20,3)); } EnemyPlaneMng.prototype={ planes:[], // 得到lowerLimit到upperlimit(包括端点值)的随机整数 getRndBetween:function (lowerLimit,upperLimit){ return Math.floor(Math.random()*(upperLimit-lowerLimit+1))+lowerLimit; }, // 重新装载飞机 reload:function(){ var count=this.getAlivePlaneCount(); if(count==0){ var i=this.getRndBetween(0,this.planes.length-1); var plane=this.planes[i]; plane.visible=true; plane.destroyed=false plane.x=ctx.canvas.width/2+this.getRndBetween(-100,100); plane.y=this.getRndBetween(20,30); plane.level=this.getRndBetween(0,7); } }, // 得到屏幕上飞机活着的飞机数目 getAlivePlaneCount:function(){ var retval=0; for(var i=0;i<this.planes.length;i++){ var plane=this.planes[i]; if(plane.visible==true && plane.destroyed==false){ retval++; } } return retval; }, paint:function(ctx){ for(var i=0;i<this.planes.length;i++){ var plane=this.planes[i]; plane.paint(ctx); } }, move:function(){ for(var i=0;i<this.planes.length;i++){ var plane=this.planes[i]; plane.move(); } }, isShooted:function(shell){ if(shell.destroyed==true){ return false; } for(var i=0;i<this.planes.length;i++){ var plane=this.planes[i]; if(plane.visible==true && plane.destroyed==false){ if(plane.isWithinLimits(shell.x,shell.y)){ plane.destroyed=true; shell.destroyed=true; // 制造爆炸 explosionMng.fire(shell.x,shell.y); // 敌机重载 enemyPlaneMng.reload(); return true; } } } return false; }, // 看主角飞机是否与敌机相撞 isCrashed:function(rolePlane){ if(rolePlane.destroyed==true){ return false; } // 得到本机四角坐标 var p1=rolePlane.getLeftUpPoint(); var p2=rolePlane.getRightUpPoint(); var p3=rolePlane.getLeftDownPoint(); var p4=rolePlane.getRightDownPoint(); for(var i=0;i<this.planes.length;i++){ var ep=this.planes[i]; if(ep.visible==true && ep.destroyed==false){ if(ep.isWithinLimits(p1.x,p1.y) || ep.isWithinLimits(p2.x,p2.y) || ep.isWithinLimits(p3.x,p3.y) || ep.isWithinLimits(p4.x,p4.y)){ ep.destroyed=true;// 敌机撞毁 explosionMng.fire(ep.x,ep.y);// 制造爆炸 // 本机撞毁后不用敌机重载 //enemyPlaneMng.reload(); rolePlane.destroyed=true;// 本机撞毁 explosionMng.fire(rolePlane.x,rolePlane.y);// 制造爆炸 // 游戏结束 return true; } } } return false; }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<敌方飞机管理类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>爆炸类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Explosion=function(x,y){ Point.apply(this,arguments); this.types=[ {width:105,height:100,file:'explosion0.png'}, {width:105,height:100,file:'explosion1.png'}, {width:105,height:100,file:'explosion2.png'}, {width:105,height:100,file:'explosion3.png'}, {width:105,height:100,file:'explosion4.png'}, {width:105,height:100,file:'explosion5.png'}, ]; } Explosion.prototype={ types:[], // 爆炸图片 destroyTime:0, // 被摧毁时间 paint:function(ctx){ var index=Math.floor(this.destroyTime); if(index<this.types.length){ this.destroyTime+=0.05; var img=new Image(); img.src=this.types[index].file; ctx.drawImage(img,this.x-this.types[index].width/2,this.y-this.types[index].height/2); } }, // 看这个爆炸对象是否使用过 isUsed:function(){ return this.destroyTime>=this.types.length; }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<爆炸类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>爆炸管理类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ExplosionMng=function(x,y){ exps=new Array(); } ExplosionMng.prototype={ exps:[], // 爆炸数组 paint:function(ctx){ for(var i=0;i<exps.length;i++){ var e=exps[i]; e.paint(ctx); } }, // 制作一次爆炸,使用这种方式,可最大程度利用现有对象,而不是创建一堆用不上的变量 fire:function(x,y){ var exp=null; for(var i=0;i<exps.length;i++){ var e=exps[i]; //console.log('e.isUsed=',e.isUsed()) if(e.isUsed()==true){ exp=e; exp.x=x; exp.y=y; exp.destroyTime=0; //console.log('使用一个原有对象',exp) break; } } if(exp==null){ exp=new Explosion(x,y); exps.push(exp); //console.log('创建一个新对象',exp) } //console.log('爆炸对象个数=',exps.length) }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<爆炸管理类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>敌方炮弹类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 19.3.16 EnemyShell=function(x,y){ Point.apply(this,arguments); this.types=[ {width:11,height:11,file:'shell0.png'}, {width:11,height:11,file:'shell1.png'}, {width:11,height:11,file:'shell2.png'}, {width:11,height:11,file:'shell3.png'}, {width:11,height:11,file:'shell4.png'}, {width:11,height:11,file:'shell5.png'}, {width:11,height:11,file:'shell6.png'}, {width:18,height:18,file:'shell7.png'}, ]; } EnemyShell.prototype={ types:[], // 炮弹型号 destroyed:false,// 是否被敌机撞毁 visible:true, // 是否在CTX显示范围内 level:0, // 等级,用以决定炮弹型号 speed:4, // 炮弹速度(敌方炮弹向下飞行) paint:function(ctx){ if(this.visible==false){ return; } if(this.destroyed==false){ // 没被击毁显示炮弹型号 var img=new Image(); var index=this.level; img.src=this.types[index].file; ctx.drawImage(img,this.x-this.types[index].width/2,this.y-this.types[index].height/2); } }, move:function(){ // 设置越界不可见 if(this.x<0){ this.visible=false; } if(this.x>ctx.canvas.width){ this.visible=false; } if(this.y<0){ this.visible=false; } if(this.y>ctx.canvas.height){ this.visible=false; } if(this.visible==true && this.destroyed==false){ this.y+=this.speed; } }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<敌方炮弹类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>敌方炮弹管理者类定义开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>19.3.16 EnemyShellMng=function(){ shells=new Array(); } EnemyShellMng.prototype={ shells:[], // 己方炮弹对象数组 paint:function(ctx){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; s.paint(ctx); } }, // 取出子弹,count为个数 fetch:function(count){ var retval=new Array(); console.log("原有敌方炮弹数量=",this.shells.length); // 先取原有的炮弹 for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; if(s.visible==false || s.destroyed==true){ s.destroyed=false; s.visible=true; if(retval.length<count){ retval.push(s); } } } // 不足再创建新的炮弹 while(retval.length<count){ var s=new EnemyShell(0,0); this.shells.push(s); retval.push(s); } console.log("现有敌方炮弹数量=",this.shells.length); return retval; }, // 移动炮弹 move:function(){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; s.move(); } }, // 判断炮弹是否撞到本机 probeCrashedMyPlane:function(){ for(var i=0;i<this.shells.length;i++){ var s=this.shells[i]; if(s.visible==true && s.destroyed==false && myPlane.destroyed==false){ if(myPlane.isShooted(s)==true){ s.destroyed=true; return; } } } }, } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<敌方炮弹管理者类定义结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //--> </script>
2019年3月16日15点45分
[Canvas]空战游戏 已经可以玩了 1.13Playable的更多相关文章
- [canvas]空战游戏1.18
空战游戏到今天可以玩了,玩法还是方向键(或AWSD)控制飞机位置,空格键开炮,吃五星升级,被敌机打中降级直到击落,与敌机相撞则GG. 点此下载程序1.16版,用CHrome打开index.html试玩 ...
- [Canvas]空战游戏进阶 增加己方子弹管理类
点此下载源码,可用Chrome打开观看. 图例: 代码: <!DOCTYPE html> <html lang="utf-8"> <meta http ...
- [Canvas]空战游戏进阶 增加爆炸管理类
点此下载源码,欲观看效果请用Chrome打开index.html 图例: 源码: <!DOCTYPE html> <html lang="utf-8"> & ...
- [Canvas]空战游戏进阶 增加发射子弹 敌机中弹爆炸功能
点此下载源码. 图例: 源码: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv=" ...
- 两个Canvas小游戏
或许连小游戏都算不上,可以叫做mini游戏. 没有任何框架或者稍微有点深度的东西,所以有js基础的或者要追求炫酷效果的可以直接ctrl+w了. 先贴出两个游戏的试玩地址: 是男人就走30步 是男人就忍 ...
- canvas小游戏——flappy bird
前言 如果说学编程就是学逻辑的话,那锻炼逻辑能力的最好方法就莫过于写游戏了.最近看了一位大神的fly bird小游戏,感觉很有帮助.于是为了寻求进一步的提高,我花了两天时间自己写了一个canvas版本 ...
- 如何开发一个简单的HTML5 Canvas 小游戏
原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...
- canvas 进入游戏点击时苹果手机为什么会闪
canvas 进入游戏点击时苹果手机为什么会闪 ?? 大神门 谁有解决办法???
- 【30分钟学完】canvas动画|游戏基础(1):理论先行
前言 本文虽说是基础教程,但这是相对动画/游戏领域来说,在前端领域算是中级教程了,不适合前端小白或萌新.阅读前请确保自己对前端三大件(JavaScript+CSS+HTML)的基础已经十分熟悉,而且有 ...
随机推荐
- Cloudera Manager的安装
1. cloudera manager的概念 简单来说,Cloudera Manager是一个拥有集群自动化安装.中心化管理.集群监控.报警功能的一个工具(软件),使得安装集群从几天的时间缩短在几个 ...
- 041 Spring Boot中排除功能的处理
这个问题,原本是没有注意,主要是理解的不够深刻. 1.先看我的配置文件 package com.springBoot.ioc.config; import com.springBoot.ioc.con ...
- day70 cookie & session 前后端交互分页显示
本文转载自qimi博客,cnblog.liwenzhou.com 概要: 我们的cookie是保存在浏览器中的键值对 为什么要有cookie? 我们在访问浏览器的时候,千万个人访问同一个页面,我们只要 ...
- ZOJ 3769-Diablo III(DP)
描述 Diablo III is an action role-playing video game. A few days ago, Reaper of Souls (ROS), the new e ...
- ELM:ELM实现鸢尾花种类测试集预测识别正确率(better)结果对比—Jason niu
load iris_data.mat P_train = []; T_train = []; P_test = []; T_test = []; for i = 1:3 temp_input = fe ...
- How to check for null/empty/whitespace values with a single test?
SELECT column_name FROM table_name WHERE TRIM(column_name) IS NULL
- 页面中去除浮动 clear:both
今天写代码发现一个很奇怪的问题,发现上面的div加浮动(不管是否包含div)以后对下面div的浮动有所影响,通过去除浮动,搞定: 只需要在受影响的div中的样式中,加入clear:both即可
- new关键字对构造函数做了什么
new 命令 基本用法 new 命令的作用,就是执行构造函数,返回一个实例对象. 1 var Vehicle = function (){ 2 this.price = 1000; 3 }; 4 5 ...
- Spring使用笔记(二)Bean装配
Bean装配 Spring提供了3种装配机制: 1)隐式的Bean发现机制和自动装配 2)在Java中进行显示装配 3)在XML中进行显示装配 一)自动化装配 1.指定某类为组件类: @Compone ...
- VirtWire 向客服发ticket
1 首先需要登录自己的账户 2 点击网页的Open Ticket 3 选择要发送何种类型的ticket 4 写自己的问题,包括一个合适的主题,选择你发ticket是针对哪个vps(一个账户下可以ord ...