js实现飞机大战小游戏

用JavaScript来实现一个鼠标指针控制的飞机大战小程序,效果图如下。

1.进入页面阶段

  

2.第二载入阶段效果图

3.第三核心阶段

  

4.第四暂停阶段

5.第五结束阶段

实现这个项目的HTML代码只需要一行,创建一个画布并且设置宽高到合适,并且要将画布设置为块级元素。

<canvas id="canvas" width="480" height="650"></canvas>

由上图可知,这个游戏分为4个阶段,在写项目之前先分析一下每个项目都需要做什么工作。

1.第一阶段:加载背景图片,然后不停的运动,并且在图片上加一个logo。

2.第二阶段是游戏的过度阶段,加载过度界面,出现一个小飞机飘过。

3.第三阶段是游戏的核心阶段。

  3.1设置自己的英雄飞机的的动态效果和移动方法,并且考虑到飞机发生碰撞的情况进行判断。

  3.2 子弹的绘制以及子弹的运动,还有子弹碰到敌方飞机的时候的改变。

  3.3 设置地方飞机的绘制和移动,以及敌方飞机的各个属性和与子弹发生碰撞的情况,和与英雄飞机发生碰撞的情况。

4.第四阶段判断鼠标一处画布的时候游戏暂停

5.当生命值为0的时候进入游戏的第五阶段,GAMEOVER。

下面是这个项目的核心JavaScript代码

  1         var canvas = document.getElementById("canvas");
  2         var context = canvas.getContext("2d");
  3 
  4         // 0  游戏初始化的一些数据
  5             // 0.1 把上面游戏的五个阶段整理成数字
  6             const START = 0;
  7             const STARTTING = 1;
  8             const RUNNING = 2;
  9             const PAUSE = 3;
 10             const GAMEOVER = 4;
 11             // 0.2 定义一个自己的状态,时刻跟上面的五个状态进行比较,然后判断游戏目前处于哪个阶段
 12             var state = START;
 13             // 0.3 画布的信息得获取过来
 14             const WIDTH = 480;
 15             const HEIGHT = 650;
 16             // 0.4 游戏的分数
 17             var score = 0;
 18             // 0.5 我方飞机的生命
 19             var life = 3;
 20         // 1  第一阶段 游戏欢迎阶段
 21             // 1.1 加载背景图片
 22             // 1.1.1  创建背景图片的dom对象
 23             var bg = new Image();
 24             bg.src = "images/background.png";
 25             // 1.1.2  背景图片的详细信息(用对象表示)
 26             var BG = {
 27                 imgs : bg,
 28                 width : 480,
 29                 height : 852
 30             }
 31             // 1.1.3  自定义构造函数,构造背景图片的
 32             function Bg(config){
 33                 this.imgs = config.imgs;
 34                 this.width = config.width;
 35                 this.height = config.height;
 36                 // 定义绘制背景图片的坐标
 37                 this.x1 = 0;
 38                 this.y1 = 0;
 39                 this.x2 = 0;
 40                 this.y2 = -this.height;
 41                 // 定义绘制方法
 42                 this.paint = function(){
 43                     context.drawImage(this.imgs,this.x1,this.y1);
 44                     context.drawImage(this.imgs,this.x2,this.y2);
 45                 }
 46                 //图片要运动
 47                 this.step = function(){
 48                     this.y1++;
 49                     this.y2++;
 50                     // 判断图片的临界值
 51                     if(this.y1 == this.height){
 52                         this.y1 = -this.height;
 53                     }
 54                     if(this.y2 == this.height){
 55                         this.y2 = -this.height;
 56                     }
 57                 }
 58             }
 59             // 1.1.4 创建背景图片的对象
 60             var abc = new Bg(BG)
 61             // 1.2 加载LOGO
 62             var logo = new Image();
 63             logo.src = "images/start.png";
 64         // 2  第二阶段 游戏过渡阶段
 65             // 2.1 创建图片的构造
 66             var loadings = [];
 67             loadings[0] = new Image();
 68             loadings[0].src = "images/game_loading1.png";
 69             loadings[1] = new Image();
 70             loadings[1].src = "images/game_loading2.png";
 71             loadings[2] = new Image();
 72             loadings[2].src = "images/game_loading3.png";
 73             loadings[3] = new Image();
 74             loadings[3].src = "images/game_loading4.png"
 75             // 2.2 图片的详细信息
 76             var LOADINGS = {
 77                 imgs : loadings,
 78                 length : loadings.length,
 79                 width : 186,
 80                 height : 38
 81             }
 82             // 2.3 动画效果的构造
 83             function Loading(config){
 84                 this.imgs = config.imgs;
 85                 this.length = config.length;
 86                 this.width = config.width;
 87                 this.height = config.height;
 88                 // 在数组中去寻找图片。得定义一个索引。
 89                 this.startIndex = 0;
 90                 // 开始绘制
 91                 this.paint = function(){
 92                     context.drawImage(this.imgs[this.startIndex],0,HEIGHT - this.height);
 93                 }
 94                 // 定义一个速度
 95                 this.time = 0;
 96                 // 运动方法
 97                 this.step = function(){
 98                     this.time ++;
 99                     if(this.time % 5 == 0){
100                         this.startIndex ++;
101                     }
102                     // 临界点,图片加载完成以后,到第三阶段去
103                     if(this.startIndex == this.length){
104                         state = RUNNING;
105                     }
106                 }
107             }
108             // 2.4 动画效果的对象
109             var loading = new Loading(LOADINGS);
110             // 2.5 onclick
111             canvas.onclick = function(){
112                 if(state == START){
113                     state = STARTTING;
114                 }
115             }
116         // 3  第三阶段 游戏运行中
117         // 3.1 绘制我方飞机
118         // 3.1.1 加载我方飞机的图片(1.飞机正常运行的状态,2.飞机碰撞以后的状态)
119         var heros = [];
120         heros[0] = new Image();
121         heros[0].src = "images/hero1.png";
122         heros[1] = new Image();
123         heros[1].src = "images/hero2.png";
124 
125         heros[2] = new Image();
126         heros[2].src = "images/hero_blowup_n1.png";
127         heros[3] = new Image();
128         heros[3].src = "images/hero_blowup_n2.png";
129         heros[4] = new Image();
130         heros[4].src = "images/hero_blowup_n3.png";
131         heros[5] = new Image();
132         heros[5].src = "images/hero_blowup_n4.png";
133         // 3.1.2 初始化我方飞机的数据
134         var HEROS = {
135             imgs : heros,
136             length : heros.length,
137             width : 99,
138             height : 124,
139             frame : 2    //添加一个状态
140         }
141         // 3.1.3 我方飞机的构造函数
142         function Hero(config){
143             this.imgs = config.imgs;
144             this.length = config.length;
145             this.width = config.width;
146             this.height = config.height;
147             this.frame = config.frame;
148             // 定义索引值
149             this.startIndex = 0;
150             // 定义飞机的坐标
151             this.x = WIDTH/2 - this.width/2;
152             this.y = HEIGHT - 150;
153             // 增加一个标识,表示飞机是否发生了碰撞,给个false,表示一直没有碰撞
154             this.down = false;
155             // 增加一个标识,表示飞机碰撞以后,碰撞的动画,碰撞的动画是否执行完成
156             this.candel = false;
157 
158             // 绘制方法
159             this.paint = function(){
160                 context.drawImage(this.imgs[this.startIndex],this.x,this.y);
161             }
162             // 运动方法
163             this.step = function(){
164                 // 监测飞机是否碰撞的属性,如果没有碰撞,索引在0和1之间切换
165                 if(!this.down){
166                     // 没有碰撞,切换索引
167                     if(this.startIndex == 0){
168                         this.startIndex = 1;
169                     }else{
170                         this.startIndex = 0;
171                     }
172                 }else{
173                     // 飞机发生了碰撞
174                     this.startIndex++;
175                     if(this.startIndex == this.length){
176                         life -- ;
177                         if(life == 0){
178                             state = GAMEOVER;
179                             this.startIndex = this.length - 1;
180                         }else{
181                             hero = new Hero(HEROS);
182                         }
183                     }
184                 }
185             }
186             this.time = 0;
187             //射击方法
188             this.shoot = function(){
189                 this.time ++;
190                 if(this.time % 4 == 0){
191                     bullets.push(new Bullet(BULLET));
192                 }    
193             }
194             this.bang = function(){
195                 this.down = true;
196             }
197         }
198         // 3.1.4 创建对象
199         var hero = new Hero(HEROS);
200         // 3.1.5 飞机跟随鼠标移动
201         canvas.onmousemove = function(event){
202             if(state == RUNNING){
203                 var x = event.offsetX;
204                 var y = event.offsetY;
205                 // 直接赋值给飞机的x和y坐标
206                 hero.x = x - hero.width/2;
207                 hero.y = y - hero.height/2;
208             }
209         }
210         // 3.2 绘制子弹
211         // 3.2.1 加载子弹的图片
212         var bullet = new Image();
213         bullet.src = "images/bullet1.png";
214         // 3.2.2 初始化子弹的数据
215         var BULLET = {
216             imgs : bullet,
217             width : 9,
218             height : 21
219         }
220         // 3.2.3 子弹的构造函数
221         function Bullet(config){
222             this.imgs = config.imgs;
223             this.width = config.width;
224             this.height = config.height;
225             // 坐标
226             this.x = hero.x + hero.width/2 - this.width/2;
227             this.y = hero.y - this.height;
228             // 绘制
229             this.paint = function(){
230                 context.drawImage(this.imgs,this.x,this.y);
231             }
232             // 运动
233             this.step = function(){
234                 this.y -= 10;
235             }
236             // 加上一个标识,标识子弹是否发生碰撞
237             this.candel = false;
238             // 撞击的方法,用于修改子弹是否碰撞的属性
239             this.bang = function(){
240                 this.candel = true;
241             }
242         }
243         // 3.2.4 增加一个数组,用来存储子弹
244         var bullets = [];
245         // 3.2.5 绘制数组里面的所有的子弹
246         function bulletsPaint(){
247             for(var i = 0;i < bullets.length;i++){
248                 bullets[i].paint()
249             }
250         }
251         // 3.2.6 绘制数组里面的所有的子弹的运动
252         function bulletsStep(){
253             for(var i = 0;i < bullets.length;i++){
254                 bullets[i].step()
255             }
256         }
257         // 3.2.7 当子弹移出画布的时候和发生碰撞以后,要把子弹从数组中删除
258         function bulletsDel(){
259             for(var i = 0;i < bullets.length;i++){
260                 if(bullets[i].y < -bullets[i].height || bullets[i].candel){
261                     bullets.splice(i,1);
262                 }
263             }
264         }
265         // 3.3 绘制地方飞机
266         // 3.3.1 加载敌方飞机的图片(3种)
267         // 小飞机
268         var enemy1 = [];
269         enemy1[0] = new Image();
270         enemy1[0].src = "images/enemy1.png";
271         enemy1[1] = new Image();
272         enemy1[1].src = "images/enemy1_down1.png";
273         enemy1[2] = new Image();
274         enemy1[2].src = "images/enemy1_down2.png";
275         enemy1[3] = new Image();
276         enemy1[3].src = "images/enemy1_down3.png";
277         enemy1[4] = new Image();
278         enemy1[4].src = "images/enemy1_down4.png";
279         // 中飞机
280         var enemy2 = [];
281         enemy2[0] = new Image();
282         enemy2[0].src = "images/enemy2.png";
283         enemy2[1] = new Image();
284         enemy2[1].src = "images/enemy2_down1.png";
285         enemy2[2] = new Image();
286         enemy2[2].src = "images/enemy2_down2.png";
287         enemy2[3] = new Image();
288         enemy2[3].src = "images/enemy2_down3.png";
289         enemy2[4] = new Image();
290         enemy2[4].src = "images/enemy2_down4.png";
291         // 大飞机
292         var enemy3 = [];
293         enemy3[0] = new Image();
294         enemy3[0].src = "images/enemy3_n1.png";
295         enemy3[1] = new Image();
296         enemy3[1].src = "images/enemy3_n2.png";
297         enemy3[2] = new Image();
298         enemy3[2].src = "images/enemy3_down1.png";
299         enemy3[3] = new Image();
300         enemy3[3].src = "images/enemy3_down2.png";
301         enemy3[4] = new Image();
302         enemy3[4].src = "images/enemy3_down3.png";
303         enemy3[5] = new Image();
304         enemy3[5].src = "images/enemy3_down4.png";
305         enemy3[6] = new Image();
306         enemy3[6].src = "images/enemy3_down5.png";
307         enemy3[7] = new Image();
308         enemy3[7].src = "images/enemy3_down6.png";
309         // 3.3.2 初始化敌方飞机的数据
310         var ENEMY1 = {
311             imgs : enemy1,
312             length : enemy1.length,
313             width : 57,
314             height : 51,
315             type : 1,    //增加一个类型,判断是哪一种飞机
316             frame : 1,
317             life : 1,
318             score : 1
319         }
320         var ENEMY2 = {
321             imgs : enemy2,
322             length : enemy2.length,
323             width : 69,
324             height : 95,
325             type : 2,    //增加一个类型,判断是哪一种飞机
326             frame : 1,
327             life : 5,
328             score : 5
329         }
330         var ENEMY3 = {
331             imgs : enemy3,
332             length : enemy3.length,
333             width : 169,
334             height : 258,
335             type : 3,    //增加一个类型,判断是哪一种飞机
336             frame : 2,
337             life : 10,
338             score : 10
339         }
340         // 3.3.3 敌方飞机的构造函数
341         function Enemy(config){
342             this.imgs = config.imgs;
343             this.length = config.length;
344             this.width = config.width;
345             this.height = config.height;
346             this.type = config.type;
347             this.frame = config.frame;
348             this.life = config.life;
349             this.score = config.score;
350             // 坐标
351             this.x = Math.random() * (WIDTH - this.width);
352             this.y = -this.height;
353             // 索引
354             this.startIndex = 0;
355             // 增加一个标识,表示飞机是否发生了碰撞,给个false,表示一直没有碰撞
356             this.down = false;
357             // 增加一个标识,表示飞机碰撞以后,碰撞的动画,碰撞的动画是否执行完成
358             this.candel = false;
359             // 绘制
360             this.paint = function(){
361                 context.drawImage(this.imgs[this.startIndex],this.x,this.y);
362             }
363             // 运动
364             this.step = function(){
365                 if(!this.down){
366                     // 根据飞机的状态来判定飞机是否由动画,就是要大飞机有动画效果
367                     this.startIndex ++;
368                     // 小飞机和中飞机就是0,大飞机是在0和1之间切换
369                     this.startIndex = this.startIndex % this.frame;
370                     this.y ++;
371                 }else{
372                     this.startIndex++;
373                     if(this.startIndex == this.length){
374                         this.candel = true;
375                         this.startIndex = this.length - 1;
376                     }
377                 }
378             }
379             this.checkHit = function(zd){   //这个参数可能是子弹,可能是我方飞机
380                 return zd.y + zd.height > this.y
381                 && zd.x + zd.width > this.x
382                 && zd.y < this.y + this.height
383                 && zd.x < this.x + this.width
384             }
385             // 撞击的方法,用于修改飞机是否碰撞的属性
386             this.bang = function(){
387                 this.life -- ;
388                 if(this.life == 0){
389                     this.down = true;
390                     score += this.score;
391                 }
392             }
393         }
394         // 3.3.4 创建数组,用于存储敌方飞机
395         var enemies = [];
396         // 3.3.5 数组中去添加飞机
397         function pushEnemies(){
398             var numRand = Math.floor(Math.random() * 100);
399             if(numRand < 10){
400                 enemies.push(new Enemy(ENEMY1))
401             }else if(numRand > 98){
402                 enemies.push(new Enemy(ENEMY2))
403             }else if(numRand == 50){
404                 enemies.push(new Enemy(ENEMY3))
405             }
406         }
407         // 3.3.6 敌方飞机的绘制函数
408         function paintEnemies(){
409             for(var i = 0;i < enemies.length;i++){
410                 enemies[i].paint()
411             }
412         }
413         // 3.3.7 敌方飞机的运动函数
414         function stepEnemies(){
415             for(var i = 0;i < enemies.length;i++){
416                 enemies[i].step()
417             }
418         }
419         // 3.3.8 敌方飞机的删除函数
420         function delEnemies(){
421             for(var i = 0;i < enemies.length;i++){
422                 // 两种情况
423                 if(enemies[i].y > HEIGHT || enemies[i].candel){
424                     enemies.splice(i,1);
425                 }
426             }
427         }
428         // 3.4 检测是否撞击
429         function hitEnemies(){
430             for(var i = 0;i < enemies.length;i++){
431                 // 自己飞机撞
432                 if(enemies[i].checkHit(hero)){
433                     enemies[i].bang();
434                     hero.bang();
435                 }
436                 // 子弹撞
437                 for(var j = 0;j < bullets.length;j++){
438                     if(enemies[i].checkHit(bullets[j])){
439                         enemies[i].bang();
440                         bullets[j].bang();
441                     }
442                 }
443             }
444         }
445         // 3.5 文本函数
446         function paintText(){
447             context.font = "bold 30px 微软雅黑";
448             context.fillText("SCORE:" + score,20,20);
449             context.fillText("LIFE:" + life,300,20);
450         }
451 
452         // 4  第四阶段 游戏暂停
453         canvas.onmouseout = function(){
454             if(state == RUNNING){
455                 state = PAUSE;
456             }
457         }
458         canvas.onmouseover = function(){
459             if(state == PAUSE){
460                 state = RUNNING;
461             }
462         }
463         var pause = new Image();
464         pause.src = "images/game_pause_nor.png";
465         // 5  第五阶段 游戏GG
466         function paintOver(){
467             context.font = "bold 50px 微软雅黑";
468             context.fillText("GAME OVER!!!",50,250);
469         }
470 
471 
472 
473 
474 
475         setInterval(function(){
476             abc.paint();
477             abc.step();
478             switch (state) {
479                 case START:
480                     context.drawImage(logo,40,0)
481                     break;
482 
483                 case STARTTING:
484                     loading.paint();
485                     loading.step();
486                     break;
487 
488                 case RUNNING:
489                     hero.paint();
490                     hero.step();
491                     hero.shoot();
492 
493                     bulletsPaint();
494                     bulletsStep();
495                     bulletsDel();
496 
497                     pushEnemies();
498                     paintEnemies();
499                     stepEnemies();
500                     delEnemies();
501 
502                     hitEnemies();
503 
504                     paintText();
505                     break;
506 
507                 case PAUSE:
508                     hero.paint();
509 
510                     bulletsPaint();
511 
512                     paintEnemies();
513 
514                     paintText();
515 
516                     context.drawImage(pause,150,350);
517                     break;
518 
519                 case GAMEOVER:
520                     hero.paint();
521 
522                     bulletsPaint();
523 
524                     paintEnemies();
525 
526                     paintText();
527 
528                     paintOver()
529                     break;
530 
531             }
532         },10)
533 
534     </script>

猜你喜欢

转载自www.cnblogs.com/wangzheng98/p/11129305.html