canvas完成飞机打怪兽射击小手机游戏的示例编码

日期:2021-02-27 类型:科技新闻 

关键词:上线了小程序官网,年会抽奖小程序免费,做小程序,小程序网站,跑腿小程序

触碰 canvas 也仅有1个多月,第1次详细完成1个手机游戏步骤,获得還是挺大的。

射击手机游戏截图

先上 demo:https://littleyljy.github.io/demo/shootgame/

手机游戏标准

规定玩家操纵飞机发射炮弹,解决会挪动的怪兽,假如所有解决了则手机游戏取得成功,假如怪兽挪动究竟部则手机游戏不成功。

  • 应用 ← 和 → 实际操作飞机
  • 应用空格(space)开展射击
  • 需有中止作用
  • 多关卡

情景切换

手机游戏分成几个情景:

  • 刚开始手机游戏(.game-intro)
  • 手机游戏中(#canvas)
  • 手机游戏不成功(.game-failed)
  • 手机游戏取得成功(.game-success)
  • 手机游戏通关(.game-all-success)
  • 中止(.game-stop)

完成情景切换,实际上是先把全部情景 display: none , 随后根据 js 操纵 data-status 各自为 start 、playing 、failed 、success 、all-success 、stop 来完成对应情景 display: block 。

HTML 和 CSS 以下:

  <div id="game" data-status="start"> 
    <div class="game-panel">
      <section class="game-intro game-ui">
        <h1 class="section-title">射击手机游戏</h1>
        <p class="game-desc">这是1个让人招架不住的射击手机游戏,应用 ← 和 → 实际操作你的飞机,应用空格(space)开展射击,应用回车(enter)中止手机游戏。1起来解决宇宙怪兽吧!</p>
        <p class="game-level">当今Level: 1</p>
        <button class="js-play button">刚开始手机游戏</button>
      </section>
      <section class="game-failed game-ui">
        <h1 class="section-title">手机游戏完毕</h1>
        <p class="game-info-text">最后得分: <span class="score"></span></p>
        <button class="js-replay button">再次刚开始</button>
      </section>
      <section class="game-success game-ui">
        <h1 class="section-title">手机游戏取得成功</h1>
        <p class="game-next-level game-info-text"></p>
        <button class="js-next button">再次手机游戏</button>
      </section>
      <section class="game-all-success game-ui">
        <h1 class="section-title">通关取得成功</h1>
        <p class="game-next-level game-info-text">你早已取得成功地防御力了怪兽的全部进攻。</p>
        <button class="js-replay button">再玩1次</button>
      </section>
      <section class="game-stop game-ui">
        <h1 class="section-title">手机游戏中止</h1>
        <button class="js-stop button">手机游戏再次</button>
      </section>
    </div>
    <div class="game-info game-ui">
      <span class="title">分数:</span>
      <span class="score"></span>
    </div>
    <canvas id="canvas" width="700" height="600">
        <!-- 动漫画板 -->
    </canvas>
  </div>
#game{
  width: 700px;
  height: 600px;
  position: relative;
  left: 50%;
  top: 40px;
  margin: 0 0 0 ⑶50px;
  background: linear-gradient(⑴80deg, #040024 0%, #07165C 97%);
}

.game-ui{
  display: none;
  padding: 55px;
  box-sizing: border-box;
    height: 100%;
}

[data-status="start"] .game-intro {
  display: block;
  padding-top: 180px;
  background: url(./img/bg.png) no-repeat 430px 180px;
  background-size: 200px;
}

[data-status="playing"] .game-info {
  display: block;
  position: absolute;
  top:0;
  left:0;
  padding:20px;
}

[data-status="failed"] .game-failed,
[data-status="success"] .game-success,
[data-status="all-success"] .game-all-success,
[data-status="stop"] .game-stop{
  display: block;
  padding-top: 180px;
  background: url(./img/bg-end.png) no-repeat 380px 190px;
  background-size: 250px;
}

朝向目标

全部手机游戏能够把怪兽(Enemy)、飞机(Plane)、炮弹(Bullet)都作为目标,此外也有配备目标(CONFIG)和操纵手机游戏逻辑性的手机游戏目标(GAME)。

手机游戏有关配备

/**
  * 手机游戏有关配备
  * @type {Object}
  */
var CONFIG = {
  status: 'start', // 手机游戏刚开始默认设置为刚开始中
  level: 1, // 手机游戏默认设置级别
  totalLevel: 6, // 一共6关
  numPerLine: 7, // 手机游戏默认设置每行是多少个怪兽
  canvasPadding: 30, // 默认设置画布的间距
  bulletSize: 10, // 默认设置炮弹长度
  bulletSpeed: 10, // 默认设置炮弹的挪动速率
  enemySpeed: 2, // 默认设置敌人挪动间距
  enemySize: 50, // 默认设置敌人的规格
  enemyGap: 10,  // 默认设置敌人之间的间隔
  enemyIcon: './img/enemy.png', // 怪兽的图象
  enemyBoomIcon: './img/boom.png', // 怪兽身亡的图象
  enemyDirection: 'right', // 默认设置敌人1刚开始往右挪动
  planeSpeed: 5, // 默认设置飞机每步挪动的间距
  planeSize: {
    width: 60,
    height: 100
  }, // 默认设置飞机的规格,
  planeIcon: './img/plane.png'
};

界定父类

由于怪兽(Enemy)、飞机(Plane)、炮弹(Bullet)都有同样的 x, y, size, speed 特性和 move() 方式,因此能够界定1个父类 Element,根据子类承继父类的方法完成。

/*父类:包括x y speed move() draw()*/
var Element = function (opts) {
        this.opts = opts || {};
        //设定座标、规格、速率
        this.x = opts.x;
        this.y = opts.y;
        this.size = opts.size;
        this.speed = opts.speed;
};

Element.prototype.move = function (x, y) {
        var addX = x || 0;
        var addY = y || 0;
        this.x += addX;
        this.y += addY;
};

//承继原形的涵数
function inheritPrototype(subType, superType) {
        var proto = Object.create(superType.prototype);
        proto.constructor = subType;
        subType.prototype = proto;
}

move(x, y) 方式依据传入的 (x, y) 值自叠加。

界定怪兽

怪兽包括独有特性:怪兽情况、图象、操纵发生爆炸情况不断的 boomCount ,和 draw()、down()、direction()、booming() 方式。

/*敌人*/
var Enemy = function (opts) {
    this.opts = opts || {};
    //启用父类特性
    Element.call(this, opts);

    //独有特性情况和图象
    this.status = 'normal';//normal、booming、noomed
    this.enemyIcon = opts.enemyIcon;
    this.enemyBoomIcon = opts.enemyBoomIcon;
    this.boomCount = 0;
};
//承继Element方式
inheritPrototype(Enemy, Element);

//方式:绘图敌人
Enemy.prototype.draw = function () {
    if (this.enemyIcon && this.enemyBoomIcon) {

        switch (this.status) {
            case 'normal':
                var enemyIcon = new Image();
                enemyIcon.src = this.enemyIcon;
                ctx.drawImage(enemyIcon, this.x, this.y, this.size, this.size);
                break;
            case 'booming':
                var enemyBoomIcon = new Image();
                enemyBoomIcon.src = this.enemyBoomIcon;
                ctx.drawImage(enemyBoomIcon, this.x, this.y, this.size, this.size);
                break;
            case 'boomed':
                ctx.clearRect(this.x, this.y, this.size, this.size);
                break;
            default:
                break;
        }
    }
    return this;
};

//方式:down 向下挪动
Enemy.prototype.down = function () {
    this.move(0, this.size);
    return this;

};

//方式:上下挪动
Enemy.prototype.direction = function (direction) {
    if (direction === 'right') {
        this.move(this.speed, 0);
    } else {
        this.move(-this.speed, 0);
    }
    return this;
};

//方式:敌人发生爆炸
Enemy.prototype.booming = function () {
    this.status = 'booming';
    this.boomCount += 1;
    if (this.boomCount > 4) {
        this.status = 'boomed';
    }
    return this;
}

  • draw() 关键是依据怪兽的情况绘图不一样的图象。
  • down() 启用父类 move() 方式,传入 y 值操纵怪兽向下挪动。
  • direction() 依据传入的方位值操纵左/右挪动。
  • booming() 让发生爆炸情况不断4帧,4帧后再消退。

界定炮弹

炮弹有 fly() 、draw() 方式。

/*炮弹*/
var Bullet = function (opts) {
    this.opts = opts || {};
    Element.call(this, opts);
};

inheritPrototype(Bullet, Element);

//方式:让炮弹飞
Bullet.prototype.fly = function () {
    this.move(0, -this.speed);
    return this;
};

//方式:绘图炮弹
Bullet.prototype.draw = function () {
    ctx.beginPath();
    ctx.strokeStyle = '#fff';
    ctx.moveTo(this.x, this.y);
    ctx.lineTo(this.x, this.y - CONFIG.bulletSize);
    ctx.closePath();
    ctx.stroke();
    return this;
};

  • fly() 启用父类 move() 方式,传入 y 值操纵炮弹向上挪动。
  • draw() 由于炮弹实际上便是1条长度为 10 的平行线,根据绘图相对路径的方法画出炮弹。

界定飞机

飞机目标包括独有特性:情况、宽高、图象、横座标最大最少值,有 hasHit()、draw()、direction()、shoot()、drawBullets() 方式。

/*飞机*/
var Plane = function (opts) {
    this.opts = opts || {};
    Element.call(this, opts);

    //独有特性情况和图象
    this.status = 'normal';
    this.width = opts.width;
    this.height = opts.height;
    this.planeIcon = opts.planeIcon;
    this.minX = opts.minX;
    this.maxX = opts.maxX;
    //炮弹有关
    this.bullets = [];
    this.bulletSpeed = opts.bulletSpeed || CONFIG.bulletSpeed;
    this.bulletSize = opts.bulletSize || CONFIG.bulletSize;
};
//承继Element方式
inheritPrototype(Plane, Element);

//方式:炮弹打中总体目标
Plane.prototype.hasHit = function (enemy) {
    var bullets = this.bullets;
    for (var i = bullets.length - 1; i >= 0; i--) {
        var bullet = bullets[i];
        var isHitPosX = (enemy.x < bullet.x) && (bullet.x < (enemy.x + enemy.size));
        var isHitPosY = (enemy.y < bullet.y) && (bullet.y < (enemy.y + enemy.size));
        if (isHitPosX && isHitPosY) {
            this.bullets.splice(i, 1);
            return true;
        }
    }
    return false;
};

//方式:绘图飞机
Plane.prototype.draw = function () {
    this.drawBullets();
    var planeIcon = new Image();
    planeIcon.src = this.planeIcon;
    ctx.drawImage(planeIcon, this.x, this.y, this.width, this.height);
    return this;
};
//方式:飞机方位
Plane.prototype.direction = function (direction) {
    var speed = this.speed;
    var planeSpeed;
    if (direction === 'left') {
        planeSpeed = this.x < this.minX ? 0 : -speed;
    } else {
        planeSpeed = this.x > this.maxX ? 0 : speed;
    }
    console.log('planeSpeed:', planeSpeed);
    console.log('this.x:', this.x);
    console.log('this.minX:', this.minX);
    console.log('this.maxX:', this.maxX);
    this.move(planeSpeed, 0);
    return this;//便捷链条式启用
};
//方式:发射炮弹
Plane.prototype.shoot = function () {
    var bulletPosX = this.x + this.width / 2;
    this.bullets.push(new Bullet({
        x: bulletPosX,
        y: this.y,
        size: this.bulletSize,
        speed: this.bulletSpeed
    }));
    return this;
};
//方式:绘图炮弹
Plane.prototype.drawBullets = function () {
    var bullets = this.bullets;
    var i = bullets.length;
    while (i--) {
        var bullet = bullets[i];
        bullet.fly();
        if (bullet.y <= 0) {
            bullets.splice(i, 1);
        }
        bullet.draw();
    }
};

  • hasHit() 分辨飞机发射的炮弹是不是打中怪兽,关键是分辨炮弹的横座标是不是在[怪兽横座标,怪兽横座标+怪兽高宽比]范畴内,另外炮弹的纵座标在[怪兽纵座标,怪兽纵座标+怪兽宽度]范畴内,打中回到 true,并移除该炮弹。
  • draw() 绘图炮弹和飞机。
  • direction() 由于飞机挪动范畴有上下界限,必须分辨飞机横座标是不是抵达界限,假如抵达界限 planeSpeed 为 0,已不挪动。
  • shoot() 建立炮弹目标,储存到 bullets 数字能量数组,炮弹横座标为飞机横座标再加飞机宽度的1半。
  • drawBullets() 绘图炮弹,从数字能量数组最终往回遍历炮弹目标数字能量数组,启用炮弹 fly() 方式,假如炮弹向上飞出显示屏,则移除这颗炮弹。

界定电脑键盘恶性事件

电脑键盘恶性事件有下列几种情况:

  • keydown:客户在电脑键盘上按下某功能键时产生。1直按着某功能键则会持续开启(opera 访问器以外)。
  • keypress:客户按下1个功能键,并造成1个标识符时产生(也便是无论相近 shift、alt、ctrl 之类的键,便是说客户按了1个能在显示屏上輸出标识符的功能键 keypress 恶性事件才会开启)。1直按着某功能键则会持续开启。
  • keyup:客户释放出来某1个功能键是开启。

由于飞机必须按下左键(keyCode=37)右键(keyCode=39)时(keydown)1直挪动,释放出来时 keyup 不挪动。按下空格(keyCode=32)或上方位键(keyCode=38)时(keydown)发射炮弹,释放出来时 keyup 终止发射。此外按下次车键(keyCode=13)中止手机游戏。因此,必须界定1个 KeyBoard 目标监视 onkeydown 和 onkeyup 是不是按下或释放出来某个键。

由于上下键是分歧的,为商业保险起见,按下左键时必须把右键 设为 false。右键同理。

//电脑键盘恶性事件
var KeyBoard = function () {
  document.onkeydown = this.keydown.bind(this);
  document.onkeyup = this.keyup.bind(this);
};
//KeyBoard目标
KeyBoard.prototype = {
  pressedLeft: false,
  pressedRight: false,
  pressedUp: false,
  heldLeft: false,
  heldRight: false,
  pressedSpace: false,
  pressedEnter: false,
  keydown: function (e) {
    var key = e.keyCode;
    switch (key) {
      case 32://空格-发射炮弹
        this.pressedSpace = true;
        break;
      case 37://左方位键
        this.pressedLeft = true;
        this.heldLeft = true;
        this.pressedRight = false;
        this.heldRight = false;
        break;
      case 38://上方位键-发射炮弹
        this.pressedUp = true;
        break;
      case 39://右方位键
        this.pressedLeft = false;
        this.heldLeft = false;
        this.pressedRight = true;
        this.heldRight = true;
        break;
      case 13://回车键-中止手机游戏
        this.pressedEnter = true;
        break;
    }
  },
  keyup: function (e) {
    var key = e.keyCode;
    switch (key) {
      case 32:
        this.pressedSpace = false;
        break;
      case 37:
        this.heldLeft = false;
        this.pressedLeft = false;
        break;
      case 38:
        this.pressedUp = false;
        break;
      case 39:
        this.heldRight = false;
        this.pressedRight = false;
        break;
      case 13:
        this.pressedEnter = false;
        break;
    }
  }
};

手机游戏逻辑性

手机游戏目标(GAME)包括了全部手机游戏的逻辑性,包含init(原始化)、bindEvent(关联按钮)、setStatus(升级手机游戏情况)、play(手机游戏中)、stop(中止)、end(完毕)等,在此不进行叙述。也包括了转化成怪兽、绘图手机游戏元素等涵数。

// 全部手机游戏目标
var GAME = {
  //1系列逻辑性涵数
  //手机游戏元素涵数
}

1、原始化

原始化涵数关键是界定飞机原始座标、飞机挪动范畴、怪兽挪动范畴,和原始化分数、怪兽数字能量数组,建立 KeyBoard 目标,只实行1次。

/**
   * 原始化涵数,这个涵数只实行1次
   * @param  {object} opts 
   * @return {[type]}      [description]
   */
init: function (opts) {
    //设定opts
    var opts = Object.assign({}, opts, CONFIG);//合拼全部主要参数
    this.opts = opts;
    this.status = 'start';
    //测算飞机目标原始座标
    this.planePosX = canvasWidth / 2 - opts.planeSize.width;
    this.planePosY = canvasHeight - opts.planeSize.height - opts.canvasPadding;
    //飞机极限座标
    this.planeMinX = opts.canvasPadding;
    this.planeMaxX = canvasWidth - opts.canvasPadding - opts.planeSize.width;
    //测算敌人挪动地区
    this.enemyMinX = opts.canvasPadding;
    this.enemyMaxX = canvasWidth - opts.canvasPadding - opts.enemySize;

    //分数设定为0
    this.score = 0;
    this.enemies = [];
    this.keyBoard = new KeyBoard();

    this.bindEvent();
    this.renderLevel();
  },

2、关联按钮恶性事件

由于几个手机游戏情景中包括刚开始手机游戏(playBtn)、再次刚开始(replayBtn)、下1关手机游戏(nextBtn)、中止手机游戏再次(stopBtn)几个按钮。大家必须给不一样按钮实行不一样恶性事件。

最先界定 var self = this; 的缘故是 this 的用法。在 bindEvent 涵数中, this 指向 GAME 目标,而在 playBtn.onclick = function () {}; 中 this 指向了 playBtn ,这明显并不是大家期待的,由于 playBtn 沒有 play() 恶性事件,GAME 目标中才有。因而必须把GAME 目标取值给1个自变量 self ,随后才可以在 playBtn.onclick = function () {}; 中启用 play() 恶性事件。

必须留意的是 replayBtn 按钮在闯关不成功和通关情景都有出現,因而获得的是全部 .js-replay 的结合。随后 forEach 遍历每一个 replayBtn 按钮,重设关卡和分数,启用 play() 恶性事件。

bindEvent: function () {
    var self = this;
    var playBtn = document.querySelector('.js-play');
    var replayBtn = document.querySelectorAll('.js-replay');
    var nextBtn = document.querySelector('.js-next');
    var stopBtn = document.querySelector('.js-stop');
    // 刚开始手机游戏按钮关联
    playBtn.onclick = function () {
      self.play();
    };
    //再次刚开始手机游戏按钮关联
    replayBtn.forEach(function (e) {
      e.onclick = function () {
        self.opts.level = 1;
        self.play();
        self.score = 0;
        totalScoreText.innerText = self.score;
      };
    });
    // 下1关手机游戏按钮关联
    nextBtn.onclick = function () {
      self.opts.level += 1;
      self.play();
    };
    // 中止手机游戏再次按钮关联
    stopBtn.onclick = function () {
      self.setStatus('playing');
      self.updateElement();
    };
  },

3、转化成飞机

createPlane: function () {
  var opts = this.opts;
  this.plane = new Plane({
      x: this.planePosX,
      y: this.planePosY,
      width: opts.planeSize.width,
      height: opts.planeSize.height,
      minX: this.planeMinX,
      speed: opts.planeSpeed,
      maxX: this.planeMaxX,
      planeIcon: opts.planeIcon
    });
}

4、转化成1组怪兽

由于怪兽全是成组出現的,每关的怪兽数量也不一样,两个 for 循环系统的功效便是转化成1行怪兽,依据关数(level)提升 level 行怪兽。或提升怪兽的速率(speed: speed + i,)来提升每关难度等。

//转化成敌人
  createEnemy: function (enemyType) {
    var opts = this.opts;
    var level = opts.level;
    var enemies = this.enemies;
    var numPerLine = opts.numPerLine;
    var padding = opts.canvasPadding;
    var gap = opts.enemyGap;
    var size = opts.enemySize;
    var speed = opts.enemySpeed;
    //每升級1关敌人提升1行
    for (var i = 0; i < level; i++) {
      for (var j = 0; j < numPerLine; j++) {
      //综合性元素的主要参数
        var initOpt = {
          x: padding + j * (size + gap),
          y: padding + i * (size + gap),
          size: size,
          speed: speed,
          status: enemyType,
          enemyIcon: opts.enemyIcon,
          enemyBoomIcon: opts.enemyBoomIcon
        };
        enemies.push(new Enemy(initOpt));
      }
    }
    return enemies;
  },

5、升级怪兽

获得怪兽数字能量数组的 x 值,分辨是不是抵达画布界限,假如抵达界限则怪兽向下挪动。另外也要监视怪兽情况,一切正常情况下的怪兽是不是被打中,发生爆炸情况下的怪兽,消退的怪兽要从数字能量数组剔除,另外得分。

//升级敌人情况
  updateEnemeis: function () {
    var opts = this.opts;
    var plane = this.plane;
    var enemies = this.enemies;
    var i = enemies.length;
    var isFall = false;//敌人着落
    var enemiesX = getHorizontalBoundary(enemies);
    if (enemiesX.minX < this.enemyMinX || enemiesX.maxX >= this.enemyMaxX) {
      console.log('enemiesX.minX', enemiesX.minX);
      console.log('enemiesX.maxX', enemiesX.maxX);
      opts.enemyDirection = opts.enemyDirection === 'right' ? 'left' : 'right';
      console.log('opts.enemyDirection', opts.enemyDirection);
      isFall = true;
    }
    //循环系统升级敌人
    while (i--) {
      var enemy = enemies[i];
      if (isFall) {
        enemy.down();
      }
      enemy.direction(opts.enemyDirection);
      switch (enemy.status) {
        case 'normal':
          if (plane.hasHit(enemy)) {
            enemy.booming();
          }
          break;
        case 'booming':
          enemy.booming();
          break;
        case 'boomed':
          enemies.splice(i, 1);
          this.score += 1;
          break;
        default:
          break;
      }
    }
  },

getHorizontalBoundary 涵数的功效是遍历数字能量数组每一个元素的 x 值,挑选出更大或更小的值,从而得到数字能量数组最大和最少的 x 值。

//获得数字能量数组横向界限
function getHorizontalBoundary(array) {
  var min, max;
  array.forEach(function (item) {
    if (!min && !max) {
      min = item.x;
      max = item.x;
    } else {
      if (item.x < min) {
        min = item.x;
      }
      if (item.x > max) {
        max = item.x;
      }
    }
  });
  return {
    minX: min,
    maxX: max
  }
}

6、升级电脑键盘面板

按下次车键实行 stop() 涵数,按下左键实行飞机左移,按下右键实行飞机右移,按下空格实行飞机发射炮弹,以便不让炮弹连成1条平行线,在这里设定 keyBoard.pressedUp 和 keyBoard.pressedSpace 为 false。

  updatePanel: function () {
    var plane = this.plane;
    var keyBoard = this.keyBoard;
    if (keyBoard.pressedEnter) {
      this.stop();
      return;
    }
    if (keyBoard.pressedLeft || keyBoard.heldLeft) {
      plane.direction('left');
    }
    if (keyBoard.pressedRight || keyBoard.heldRight) {
      plane.direction('right');
    }
    if (keyBoard.pressedUp || keyBoard.pressedSpace) {
      keyBoard.pressedUp = false;
      keyBoard.pressedSpace = false;
      plane.shoot();
    }
  },

7、绘图全部元素

draw: function () {
    this.renderScore();
    this.plane.draw();
    this.enemies.forEach(function (enemy) {
      //console.log('draw:this.enemy',enemy);
      enemy.draw();
    });
  },

8、升级全部元素

最先分辨怪兽数字能量数组长度是不是为 0 ,为 0 且 level 等于 totalLevel 表明通关,不然显示信息下1关手机游戏提前准备画面;假如怪兽数字能量数组 y 座标超过飞机 y 座标加怪兽高宽比,显示信息手机游戏不成功。

canvas 动漫的基本原理便是持续绘图、升级、消除画布。

手机游戏中止的基本原理便是阻拦 requestAnimationFrame() 涵数实行,但不重设元素。因而分辨 status 的情况为 stop 时跳出来涵数。

  //升级全部元素情况
  updateElement: function () {
    var self = this;
    var opts = this.opts;
    var enemies = this.enemies;

    if (enemies.length === 0) {
      if (opts.level === opts.totalLevel) {
        this.end('all-success');
      } else {
        this.end('success');
      }
      return;
    }
    if (enemies[enemies.length - 1].y >= this.planePosY - opts.enemySize) {
      this.end('failed');
      return;
    }
    //清除画布
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    //绘图画布
    this.draw();
    //升级元素情况
    this.updatePanel();
    this.updateEnemeis();

    //持续循环系统updateElement
    requestAnimationFrame(function () {
      if(self.status === 'stop'){
        return;
      }else{
        self.updateElement();
      }
    });
  },

写在最终

根据以上几个流程,手机游戏的基础作用就进行了,别的1些手机游戏步骤操纵,包含刚开始、完毕、得分测算等在此就不描述了。

能够提升的地区:在按住空格键的情况下,能够持续发射炮弹。可是,这时候再按1正下方向键,发现没法再发射炮弹了。最好是是能挪动的情况下,也能维持着炮弹的发射。

canvas 做手机游戏還是较为趣味的,此外还能够把这个手机游戏加以拓展,改为手机上版,画布规格根据获得显示屏宽高明确,电脑键盘一部分改为触碰恶性事件(touchstart、touchmove、touchend),怪兽出現方法还可以改为从显示屏顶端任意着落,怪兽提升血量(如射击4次才消退)等。

免费下载详细地址:https://github.com/littleyljy/shoot

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。

上一篇:localStorage 设定到期時间的方式完成 返回下一篇:没有了