@[toc]飞机大战
飞机大战小游戏相关说明
需求说明
- 己方飞机与敌方飞机
- 己方发射子弹,摧毁敌方飞机
- 击毁一辆敌方飞机得分
- 己方飞机碰撞敌方飞机游戏结束统计分数
功能说明
主要功能
- 鼠标移动己方飞机
- 己方飞机发射子弹
- 敌方飞机随机生成,运动方向由上到下
- 模式难度选择:敌机的数量、敌机的移动速度等
次要功能
- 敌方不同类型飞机
- 己方不同类型飞机
技术说明
掌握基本的前端技术,熟练使用CSS、JS代码,完成游戏的布局与动态交互作用
所用的Javascript技术介绍
1、setInterval() 是 JavaScript 中的一个内置函数,它用于在指定的间隔时间内重复执行一段代码,实现周期性操作。
2、Math.random()随机数生成
3、innerHTML 是一个用于读取或设置 HTML 元素内容的属性。通过 innerHTML 属性,可以获取或修改指定元素的 HTML 内容。
4、removeChild() 方法从子节点列表中删除某个节点。如删除成功,此方法可返回被删除的节点,如失败,则返回 NULL。
5、parentNode属性,首先需要获取到一个节点对象。可以通过getElementById、getElementsByTagName等方法获取到指定的节点对象。然后,就可以使用parentNode属性来获取该节点的父节点。
6、onmousemove 监听鼠标移动事件
飞机爆炸状态与物体碰撞检测(敌机与子弹,我机与敌机碰撞)
//爆炸函数 function boom(l,t,w,h,i){ var oBoom = new Image(); // oBoom.src = "img/"+["boom_small","plane_0","boom_big"][i]+".png"; oBoom.src = "img/boom.png" oBoom.className ="boom"; oBoom.width = w; oBoom.height = h; oBoom.style.left = l + "px"; oBoom.style.top = t + 'px'; oMap.appendChild(oBoom); setTimeout(function(){ oBoom.parentNode && oMap.removeChild(oBoom); },[1200,2500,1200][i]); } //两个物体 碰撞检测 function coll( obj1 , obj2 ){ var T1 = obj1.offsetTop, B1 = T1+obj1.clientHeight, L1 = obj1.offsetLeft, R1 = L1+obj1.clientWidth; var T2 = obj2.offsetTop, B2 = T2+obj2.clientHeight, L2 = obj2.offsetLeft, R2 = L2+obj2.clientWidth; return !( B1 < T2 || R1 < L2 || T1 > B2 || L1 > R2 ); }
敌方飞机生成
function enemy(level , oPlane) { var w = oMap.clientWidth, h = oMap.clientHeight; var speed = [5,6,7,8][level]; //根据不同模式确认敌军下落速度 var num = 1; oBox.enemyIntetval = setInterval(function () { var index = num%30?1:0; var tu = Math.floor(Math.random() * 4);//0-3个随机数 //生成敌军 var oEnemy = new Image(); oEnemy.tu = tu; oEnemy.index = index; oEnemy.HP = [1,1,1,10][tu]; oEnemy.speed = speed + (Math.random()*0.6 - 0.3)*speed; oEnemy.speed *= index?1:0.5; oEnemy.src = "img/enemy_"+["1","2","3","boss"][tu]+".png"; oEnemy.className = "enemy"; oEnemy.width = [54,54,54,104][tu]; oEnemy.height = [40,40,40,80][tu]; oEnemy.style.left = Math.random()*w - oEnemy.width/2 + 'px'; oEnemy.style.top = -oEnemy.height + 'px'; oMap.appendChild(oEnemy); num ++;
敌方飞机运动轨迹设定(敌机安全下落分数减少)及与子弹的碰撞与移除(分数增加,敌方飞机爆炸与移除)
//敌军运动 function m(){ if ( oEnemy.parentNode ){ var top = oEnemy.offsetTop; top += oEnemy.speed; if ( top >= h ){ oBox.score --; //漏掉飞机减分 oScore.innerHTML = oBox.score; oMap.removeChild(oEnemy); }else{ oEnemy.style.top = top + 'px'; //子弹碰撞检测 for (var i = allBiu.length - 1 ; i >= 0; i--) { var objBiu = allBiu[i]; if ( coll(oEnemy , objBiu) ){ oBiuAll.removeChild(objBiu);//移除子弹 oEnemy.HP --; if ( !oEnemy.HP ){ oBox.score += oEnemy.index?2:20; //打掉敌方飞机加分 oScore.innerHTML = oBox.score; boom(oEnemy.offsetLeft,oEnemy.offsetTop,oEnemy.width,oEnemy.height,index?0:2);//敌军爆炸图 oMap.removeChild(oEnemy);//移除敌军 return; } } } requestAnimationFrame(m); },[350,150,120,40][level]); }
运行截图:
游戏结束与分数结算、游戏重新开始
游戏结束:即敌机与我机碰撞(其实还可以使敌机发射子弹,子弹碰撞我机减血,血量为零)游戏结束:
一、我机与敌机碰撞我机与所碰撞敌机一同销毁
//我军碰撞检测 if ( oPlane.parentNode && coll(oEnemy,oPlane) ){ boom(oEnemy.offsetLeft,oEnemy.offsetTop,oEnemy.width,oEnemy.height,index?0:2);//敌军爆炸图 boom(oPlane.offsetLeft,oPlane.offsetTop,oPlane.width,oPlane.height,1);//我军爆炸图 oMap.removeChild(oEnemy);//移除敌军 oMap.removeChild(oPlane);//移除我军 GameOver(); return; }
敌机与我机碰撞运行截图:
二、游戏结束与分数结算
//游戏结束 function GameOver(){ document.onmousemove = null; //清除移动事件 clearInterval(oBox.biuInterval);//不再产生新子弹 clearInterval(oBox.enemyIntetval);//不再产生新敌军 restart(); } //结算+重新开始 function restart(){ oScore.style.display = "none"; var s = oBox.score; var honor; if ( s < -300 ){ honor = "青铜"; }else if ( s < 10 ){ honor = "白银"; }else if ( s < 30 ){ honor = "黄金"; }else if ( s < 100 ){ honor = "钻石"; }else if ( s < 200 ){ honor = "星耀"; }else if ( s < 500 ){ honor = "初级大师"; }else if ( s < 1000 ){ honor = "中级大师"; }else if ( s < 5000 ){ honor = "高极大师"; }else{ honor = "孤独求败!!!"; } oRe.style.display = "block"; allReChild[0].children[0].innerHTML = s; allReChild[1].children[0].innerHTML = honor; }
总结
BUG:
敌方飞机卡在上面没有下来。
原因:打注释的时候不小心把功能介绍的注释给删了。注释回来就好了。
总体构思很重要,本篇笔者参考了多份飞机大战小游戏,导致了自己的思路混乱,然后函数方法具有跳跃性,前期还是要先构思好,对各个功能的实现做详细的思考,使代码不要高耦合。