[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();// 初始化CTXvar 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);// 上限越大打得越慢,这个值可以叫ShootIntervalif(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=falseplane.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分
转载于:https://www.cnblogs.com/xiandedanteng/p/10542577.html
[Canvas]空战游戏 已经可以玩了 1.13Playable相关推荐
- [canvas]空战游戏1.18
空战游戏到今天可以玩了,玩法还是方向键(或AWSD)控制飞机位置,空格键开炮,吃五星升级,被敌机打中降级直到击落,与敌机相撞则GG. 点此下载程序1.16版,用CHrome打开index.html试玩 ...
- 做游戏,学编程(C语言) 6 数组之空战游戏
利用数组,我们可以在空战游戏中实现多台敌机.发射闪弹等效果.大家可以用之前教程的思路,尝试分步骤实现:飞机的显示.单个敌机.多个敌机.发射常规子弹.发射闪弹,以下是完整的代码. #include &l ...
- c语言easyx输出文字_做游戏,学编程(C语言) 6 数组之空战游戏
利用数组,我们可以在空战游戏中实现多台敌机.发射闪弹等效果.大家可以用之前教程的思路,尝试分步骤实现:飞机的显示.单个敌机.多个敌机.发射常规子弹.发射闪弹,以下是完整的代码. #include &l ...
- 大家都在发圣诞树,我偏偏要发一个圣诞小游戏给大家玩【内附源码】
大家好,我是辣条. 前言 圣诞节快来了,热榜都被一堆圣诞树攻占了,这样的流量密码我怎么会错过,大家都发圣诞树,我就不发啦,直接分享一个圣诞小游戏给大家玩,代码太长一定要先赞和收藏. 领取福利 300 ...
- 开发一个Canvas小游戏 实现一个游戏“引擎”
前言 这个游戏其实在三四年前就写了,中间还重构过好几次,之前都是用简单的面向对象和函数式编程来写,游戏中的元素关系到还是分的挺开,但是游戏的渲染,运算等逻辑分的不够清晰,整个逻辑基本都是自顶向下的流水 ...
- HTML5 2D Canvas手机游戏开发经验谈
HTML5 2D Canvas手机游戏开发经验谈 临渊羡鱼,不如退而结网-HTML5 2DCanvas手机游戏开发经验谈 现在什么技术最火?HTML5!现在什么技术最时尚!还是HTML5!也许有泡沫和 ...
- 免费也可以很好玩,40款开源游戏任你玩(三)
竞技游戏 1.Critical Mass 敌人无处不在,你必须小心发射导弹! Critical Mass是一个射击游戏.包含了三种不同的模式, ...
- 核爆rpg手机版_好嗨游戏:不玩吃亏 ,20款全世界最佳移动RPG角色扮演游戏(上)...
文章首发于:好嗨游戏 RPG(角色扮演游戏)毫无疑问是有史以来最好的游戏类型了,它也是兼容性最好的游戏类型,可以和其他各种类型结合形成新的有趣的游戏,比如在MOBA游戏中融入RPG的元素,同时它也比其 ...
- 构建一个react项目_您想要了解更多有关React的内容吗? 让我们构建一个游戏,然后玩。...
构建一个react项目 by Samer Buna 通过Samer Buna 您想要了解更多有关React的内容吗? 让我们构建一个游戏,然后玩. (Do you want to learn more ...
最新文章
- OpenCV3.3中K-Means聚类接口简介及使用
- 微服务常见安全认证方案Session token cookie跨域
- 为何要fork()两次来避免产生僵尸进程?
- 遍历二叉树的神级方法(Morris遍历)
- linux的 su 错误 Permission denied 和 Incorrect pa...
- P7044-[MCOI-03]括号【组合数学】
- CocosCreator中TiledMap简单使用
- 缺少msvcr100.dll,小编教你丢失msvcr100.dll真正解决方法
- 网页颜色搭配,网站设计,Google logo配色 Google官方配色表
- BAT面试经验分享(机器学习算法岗)
- [论文解析] Diffusion Models Beat GANs on Image Synthesis
- Byte的数值范围为何是-128到127
- HDLBits刷题全记录(五)
- CANoe和CANoe.DiVa关于通信测试的简略汇总
- 关于SSD寿命问题的探讨
- 对地球生命的来源持有怀疑
- 基于ARM处理器的LCD控制及触摸屏接口设计
- Thinkphp里面设置url伪静态
- 2021-08-28
- 日本地图选择插件、日本地区选择插件