小时候大家应该都玩过飞机大战吧,这就是仿的一个飞机大战,但是没有写的很全,只能玩一次,死掉之后需要刷新页面玩第二次,话不说多,上代码:
初始页面:
整个的html代码还是很少,如下:
<div id="box"><!--存难度--><div id="level"><h1>飞机大战 1.0</h1><p>简单</p><p>中等</p><p>困难</p><p style="color:#f00">WM 难度</p></div><!--放地图,每个难度的地图都是不同的--><div id="map"><!--统一管理敌军--><div id="BiuAll"></div></div>
</div>
困难点:
代码的重点就是判断飞机之间的距离从而来确定是否碰撞到了,敌军与子弹的距离判断是否击落敌军
上代码:
//碰撞检测function coll(obj1,obj2) {//物体 1 的边界var T1=obj1.offsetTop,B1=T1+obj1.clientHeight,L1=obj1.offsetLeft,R1=L1+obj1.clientWidth;//物体 2 的边界var T2=obj2.offsetTop,B2=T2+obj2.clientHeight,L2=obj2.offsetLeft,R2=L2+obj2.clientWidth;if(B1<T2 ||R1<L2 ||T1>B2 || L1>R2){//没有撞到的情况return false;}else{//撞到了的情况return true;}}
子弹的碰撞检测需要倒着遍历,就像遍历数组去重一样,如果你从第一个开始遍历,若数组第一个就重复的话,删除第一个,原先的第二个会顶替到第一个的位置,会造成漏网之鱼。
1 //子弹碰撞 倒着遍历 2 for(var i=allBiu.length-1;i>=0;i--){ 3 var objBiu=allBiu[i]; 4 if(coll(oEnemy,objBiu)){ 5 boom(oEnemy.offsetLeft,oEnemy.offsetTop,0); 6 BiuAll.removeChild(objBiu); 7 oMap.removeChild(oEnemy); 8 return; 9 } 10 }
飞机的移动是用拖拽实现的,拖拽需要注意的一点就是不要把飞机拖出屏幕,需要有一个临界值,如图:
代码:
left=Math.max(-oImg.clientWidth/2,left);left=Math.min(oBox.clientWidth-oImg.clientWidth/2,left);top=Math.min(oBox.clientHeight-oImg.clientHeight/2,top);top=Math.max(0,top);oImg.style.left=left+"px";oImg.style.top=top+"px";
选择的难度不同,子弹速度不同
附上全部代码:
1 <!DOCTYPE html> 2 <html lang="en" onselectstart="return false"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="Author" content=""> 6 <title>demo1</title> 7 <style> 8 * { 9 margin: 0; 10 padding: 0; 11 font-family: Microsoft YaHei, serif; 12 } 13 14 li { 15 list-style: none; 16 } 17 18 body { 19 overflow: hidden; 20 user-select: none; 21 -moz-user-select: none; 22 -ms-user-select: none; 23 } 24 25 #box { 26 position: relative; 27 width: 512px; 28 height: 768px; 29 margin: 20px auto; 30 } 31 32 #map { 33 position: absolute; 34 top: 0; 35 left: 0; 36 width: 100%; 37 height: 100%; 38 background: url("../img/bg_1.jpg"); 39 } 40 41 #level { 42 position: absolute; 43 top: 0; 44 left: 0; 45 width: 100%; 46 height: 100%; 47 z-index: 1; 48 } 49 50 #level.hid { 51 display: none; 52 } 53 54 #level h1 { 55 font-size: 40px; 56 padding-top: 60px; 57 padding-bottom: 30px; 58 line-height: 60px; 59 text-align: center; 60 color: white; 61 } 62 63 #level p:hover { 64 background: #ee4411; 65 color: #fff; 66 } 67 68 #level p { 69 margin: 100px auto; 70 width: 200px; 71 height: 35px; 72 line-height: 35px; 73 text-align: center; 74 background: #fff; 75 font-weight: bolder; 76 cursor: pointer; 77 } 78 79 #map .plane ,#map .biu , #map .enemy,#map .boom1 ,#map .boom2{ 80 position: absolute; 81 } 82 #map .biu{ 83 z-index: 10; 84 } 85 #map .plane{ 86 z-index: 8; 87 } 88 #map .boom1{ 89 z-index: 7; 90 animation: fade 1s 2; 91 animation-fill-mode: forwards; 92 } 93 @keyframes fade{ 94 from{opacity: 1} 95 to{opacity: 0} 96 } 97 #map .enemy{ 98 z-index: 9; 99 } 100 #map .boom2{ 101 z-index: 11; 102 animation: bling 2s 1; 103 } 104 @keyframes bling { 105 0%{opacity: 1} 106 50%{opacity: 0} 107 75%{opacity: 1} 108 100%{opacity: 0} 109 } 110 111 </style> 112 </head> 113 <body> 114 <div id="box"> 115 <!--存难度--> 116 <div id="level"> 117 <h1>飞机大战 1.0</h1> 118 <p>简单</p> 119 <p>中等</p> 120 <p>困难</p> 121 <p style="color:#f00">WM 难度</p> 122 </div> 123 <!--放地图,每个难度的地图都是不同的--> 124 <div id="map"> 125 <!--统一管理敌军--> 126 <div id="BiuAll"></div> 127 </div> 128 </div> 129 <script> 130 ~function () { 131 //动画兼容 132 window.requestAnimationFrame=window.requestAnimationFrame || function (fn) { 133 return setTimeout(fn,1000/60) 134 }; 135 window.cancelAnimationFrame= window.cancelAnimationFrame || clearTimeout; 136 //获取局部的全局变量 137 var oLevel = document.getElementById("level"), 138 BiuAll=document.getElementById("BiuAll"), 139 allBiu=BiuAll.children, 140 oBox = document.getElementById("box"), 141 oMap = document.getElementById("map"), 142 boxOffsetTop = oBox.offsetTop, 143 boxOffsetLeft = oBox.offsetLeft; 144 145 //启动游戏 146 exe(); 147 148 //选择关卡 难度的点击事件 149 function exe() { 150 var aP = oLevel.getElementsByTagName("p"); 151 for (var i = 0, len = aP.length; i < len; i++) { 152 !function (i) { 153 aP[i].onclick = function (e) { 154 e = e || window.event; 155 //第一个实参为关卡难度序号 156 //第二个存储鼠标距离map边缘距离的jn 157 startGame(i, { 158 x: e.clientX - boxOffsetLeft, 159 y: e.clientY - boxOffsetTop 160 }); 161 } 162 }(i); 163 } 164 165 166 } 167 168 //开始游戏 169 function startGame(level, pos) { 170 //执行清理 171 clearMap(); 172 //执行创建我军 173 var rImg=plane(level, pos); 174 //执行敌军 175 enemy(level, rImg); 176 177 178 } 179 180 //隐藏与清理地图 181 function clearMap() { 182 //隐藏选择关卡的选择框 183 oLevel.classList.add("hid"); 184 } 185 186 //创建我军 187 function plane(level,pos) { 188 //创建飞机的我军图片 189 var oImg = new Image(); 190 oImg.src = "../img/plane_0.png"; 191 oImg.width = 70; 192 oImg.height = 70; 193 oImg.className = "plane"; 194 oImg.style.left=pos.x-oImg.width/2+"px"; 195 oImg.style.top=pos.y-oImg.height/2+"px"; 196 oMap.appendChild(oImg); 197 198 199 //加入mousemove事件 200 document.οnmοusemοve=function (e) { 201 e = e || window.event; 202 //获取飞机的实时坐标 203 var left=e.clientX-boxOffsetLeft-oImg.width/2, 204 top=e.clientY-boxOffsetTop-oImg.height/2; 205 //控制飞机的边界值 206 left=Math.max(-oImg.clientWidth/2,left); 207 left=Math.min(oBox.clientWidth-oImg.clientWidth/2,left); 208 top=Math.min(oBox.clientHeight-oImg.clientHeight/2,top); 209 top=Math.max(0,top); 210 oImg.style.left=left+"px"; 211 oImg.style.top=top+"px"; 212 213 } 214 //等级不同子弹速度不同 215 fire(oImg,level); 216 //返回出去便于敌军里面接收到这个函数 217 return oImg; 218 } 219 //我军子弹 220 function fire(oImg,level) { 221 //选择创建子弹的速率 222 var time=[100,200,200,20][level]; 223 oBox.timer=setInterval(function () { 224 //创建子弹 225 var oBiu=new Image(); 226 oBiu.src="../img/fire.png"; 227 oBiu.width=30; 228 oBiu.height=30; 229 oBiu.className="biu"; 230 oBiu.style.left=oImg.offsetLeft+oImg.width/2-oBiu.width/2 +"px"; 231 oBiu.style.top=oImg.offsetTop-oBiu.height+5+"px"; 232 BiuAll.appendChild(oBiu); 233 //子弹运动 234 function move() { 235 if(oBiu.parentNode){ 236 var top=oBiu.offsetTop-30; 237 if(top<-oBiu.height){ 238 top=-oBiu.height 239 BiuAll.removeChild(oBiu); 240 }else{ 241 oBiu.style.top=top+"px"; 242 243 requestAnimationFrame(move); 244 } 245 } 246 } 247 //用定时器把队列往后拖一下,让top不会重复计算一次 248 setTimeout(function () { 249 requestAnimationFrame(move) 250 },20); 251 252 253 },time); 254 } 255 //创建敌军 256 function enemy(level,rImg) { 257 //敌军下落速度; 258 var speed=[5,6,8,10][level]; 259 oBox.eTimer=setInterval(function () { 260 //生成敌军 261 var oEnemy=new Image(); 262 oEnemy.src="../img/enemy_small.png"; 263 oEnemy.className="enemy"; 264 oEnemy.width=54; 265 oEnemy.height=40; 266 oEnemy.style.left=Math.random()*oMap.clientWidth-oEnemy.width/2 +"px"; 267 oEnemy.style.top=-oEnemy.height+"px"; 268 oMap.appendChild(oEnemy); 269 //敌方运动 270 function move () { 271 //检测下在不在页面中; 272 if(oEnemy.parentNode){ 273 var top=oEnemy.offsetTop; 274 top+=speed; 275 if(top>=oMap.clientHeight){ 276 oMap.removeChild(oEnemy); 277 }else{ 278 oEnemy.style.top=top+"px"; 279 //子弹碰撞 倒着遍历 280 for(var i=allBiu.length-1;i>=0;i--){ 281 var objBiu=allBiu[i]; 282 if(coll(oEnemy,objBiu)){ 283 boom(oEnemy.offsetLeft,oEnemy.offsetTop,0); 284 BiuAll.removeChild(objBiu); 285 oMap.removeChild(oEnemy); 286 return; 287 } 288 } 289 //我军碰撞检测 290 if(rImg.parentNode&&coll(oEnemy,rImg)){ 291 //敌军爆炸图 292 boom(oEnemy.offsetLeft,oEnemy.offsetTop,0); 293 //我军爆炸图 294 boom(rImg.offsetLeft,rImg.offsetTop,1); 295 //移除敌军 我军; 296 oMap.removeChild(oEnemy); 297 oMap.removeChild(rImg); 298 //游戏结束 299 gameover(); 300 return; 301 } 302 requestAnimationFrame(move); 303 } 304 } 305 306 307 } 308 requestAnimationFrame(move) 309 },[350,250,120,80][level]); 310 } 311 //爆炸函数 312 function boom(l,t,i) { 313 var oBoom=new Image(); 314 oBoom.src="../img/"+["boom_small","plane_0"][i]+".png"; 315 oBoom.width=[54,70][i]; 316 oBoom.height=[40,70][i]; 317 oBoom.className=["boom1","boom2"][i]; 318 oBoom.style.left=l+"px"; 319 oBoom.style.top=t+"px"; 320 oMap.appendChild(oBoom); 321 setTimeout(function () { 322 oMap.removeChild(oBoom); 323 },[1200,2500][i]) 324 } 325 326 327 //碰撞检测 328 function coll(obj1,obj2) { 329 //物体 1 的边界 330 var T1=obj1.offsetTop, 331 B1=T1+obj1.clientHeight, 332 L1=obj1.offsetLeft, 333 R1=L1+obj1.clientWidth; 334 //物体 2 的边界 335 var T2=obj2.offsetTop, 336 B2=T2+obj2.clientHeight, 337 L2=obj2.offsetLeft, 338 R2=L2+obj2.clientWidth; 339 340 if(B1<T2 ||R1<L2 ||T1>B2 || L1>R2){ 341 //没有撞到的情况 342 return false; 343 }else{ 344 //撞到了的情况 345 return true; 346 } 347 } 348 //游戏结束 349 function gameover() { 350 //清除移动事件 351 document.οnmοusemοve=null; 352 //停止创建子弹 353 clearInterval(oBox.timer); 354 //停止创建敌军 355 clearInterval(oBox.eTimer); 356 } 357 }(); 358 359 </script> 360 </body> 361 </html>
这是1.0版本,后期我会把功能完善下,加上计分等。
上述代码有问题请各位大佬们指出,谢谢啦。如果觉得有意思的麻烦点个赞哦。