zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    Windows下Android开发环境搭建
    解决Win7下打开或关闭Windows功能空白一片
    C#中得到程序当前工作目录和执行目录的一些方法
    创业者必看的小故事
    Sql Server 2005外围应用应用配置器打不开了怎么办
    vs2005无法Web调试
    SQL Server 全局变量
    转 document.documentElement与document.body
    [转]使用SSMA将Oracle数据库转成SQL Server 2008
    Delphi 2009、C++Builder2009正式发布
  • 原文地址:https://www.cnblogs.com/wangzheng98/p/11129305.html
Copyright © 2011-2022 走看看