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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM