网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網(wǎng)

微信小游戲體驗之打飛機改造計劃

發(fā)布時間:2018-05-02 15:48 所屬欄目:小程序開發(fā)教程

微信小游戲推出已有幾天了,這個功能對小程序和小游戲的推動影響不用多說,大家趕緊摩拳擦掌往上擼就可以了。關于如何開發(fā)官方文檔已經(jīng)說明了,這篇則是對官方的 打飛機 demo一些小改造。

開發(fā)預備式

  1. 下載最新版本的 微信開發(fā)者工具 (v1.02.1712280)
  2. 根據(jù)官方文檔說明, 目前不提供公開注冊 。因此目前只能使用 無AppID 模式進行體驗
  3. 為了讓 HTML5 游戲輕松接入,官方提供了 Adapter 。這個的作用就是提供 HTML5 寫法和 wx 寫法的全局轉換層。

打飛機小游戲

使用 無AppID 模式創(chuàng)建一個微信小游戲后可以看到官方demo,其中入口文件和配置文件: game.js 和 game.json 。 game.js 引入并初始化包含整個 打飛機 的游戲場景、參與者(玩家飛機和敵方飛機)、游戲邏輯的主函數(shù)的 main.js 。在 main.js 中我們可以發(fā)現(xiàn)由于 Adapter 的存在,這里的代碼和我們平常的代碼寫法沒什么差異了。游戲的主邏輯如下圖:

 

在loop中,玩家每隔20幀射一次,每隔60幀生成新的敵機。每幀檢查玩家和敵機是否死亡,玩家死亡游戲結束,敵機死亡分數(shù)+1。只有玩家可以射擊,且射擊方式固定,通過躲避敵機生存。接下來我們針對這些進行改造,提升游戲的可玩性和挑戰(zhàn)性。

玩家升級計劃

  1. 玩家初始等級為1,玩家可通過擊殺敵機升級,每擊落30敵機升級一次
  2. 玩家每升級一次,增加一個射擊口
  3. 玩家最多升級兩次

首先用編輯器打開 player/index.js ,將等級邏輯加入到玩家的類中。


export default class Player extends Sprite {
  constructor() {
    super(PLAYER_IMG_SRC, PLAYER_WIDTH, PLAYER_HEIGHT)

    // 玩家默認處于屏幕底部居中位置
    this.x = screenWidth / 2 - this.width / 2
    this.y = screenHeight - this.height - 30

    // 用于在手指移動的時候標識手指是否已經(jīng)在飛機上了
    this.touched = false

    this.bullets = []

    // 初始化事件監(jiān)聽
    this.initEvent()

    this.playerLevel = 1;
  }

  get level () {
    return this.playerLevel;
  }
  set level (level) {
    this.playerLevel = Math.min(level, 3);
  }

接下來在 main.js 的 update 函數(shù)加入升級邏輯。


// 其他代碼...

    update() {
        this.bg.update();

        databus.bullets.concat(databus.enemys).forEach(item => {
            item.update();
        });

        this.enemyGenerate();

        this.player.level = Math.max(1, Math.ceil(databus.score / 30));

        this.collisionDetection();
    }

// 其他代碼...

好的,到此玩家已經(jīng)可以正常升級了。那么該給予玩家獎勵品了。在 player/index.js 的 shoot 函數(shù)中我們修改射擊的邏輯。玩家1級時只有中間的射擊口,2級有左邊和中間的射擊口,3級有左中右三個射擊口。


// ...其他代碼

    /**
     * 玩家射擊操作
     * 射擊時機由外部決定
     */
    shoot() {


      for(let i = 0; i < this.level; i++) {
        const bullet = databus.pool.getItemByClass('bullet', Bullet);
        const middle = this.x + this.width / 2 - bullet.width / 2;
        const x = !i ? middle : (i % 2 === 0 ? middle + 30 : middle - 30);
        bullet.init(
          x,
          this.y - 10,
          10
        )

        databus.bullets.push(bullet)
      }
    }

// ...其他代碼

武器的最終形態(tài)如圖, 這時候的玩家已經(jīng)可以為所欲為了<_<,實際上都不需要躲避了。。。:

 

敵人的反擊號角

為了對抗愚昧的玩家,不讓他們?yōu)樗麨椋詈鬀]興趣玩下去~~,敵機裝備武器,反擊開始。

首先敵機的子彈是向下,所以復制一份 images/bullet.png ,并顛倒保存為 images/bullet-down.png , 然后我們重用 js/player/bullet.js ,在構造函數(shù)處增加敵機的子彈配置項,并修改敵人子彈更新邏輯。


const BULLET_IMG_SRC = 'images/bullet.png'
const BULLET_DOWN_IMG_SRC = 'images/bullet-down.png'
const BULLET_WIDTH   = 16
const BULLET_HEIGHT  = 30

const __ = {
    speed: Symbol('speed')
}

let databus = new DataBus()

export default class Bullet extends Sprite {
    constructor({ direction } = { direction: 'up' }) {
        super(direction === 'up' ? BULLET_IMG_SRC : BULLET_DOWN_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT)
       
        this.direction = direction;

// 其他代碼...

    // 每一幀更新子彈位置
    update() {
        if (this.direction === 'up') {
            this.y -= this[__.speed] 
            
            // 超出屏幕外回收自身
            if ( this.y < -this.height )
                databus.removeBullets(this)
        } else {
            this.y += this[__.speed]

            // 超出屏幕外回收自身
            if ( this.y > window.innerHeight + this.height )
                databus.removeBullets(this)
        }
    }
}

接著在 js/npc/enemy.js 結尾部分為敵人裝備武器, 子彈速度為敵人自身速度 +5


import Animation from '../base/animation'
import DataBus   from '../databus'
import Bullet from '../player/bullet';

const ENEMY_IMG_SRC = 'images/enemy.png'
// 其他代碼...

  update() {
    this.y += this[__.speed]

    // 對象回收
    if ( this.y > window.innerHeight + this.height )
      databus.removeEnemey(this)
  }

  /**
   * 敵機射擊操作
   * 射擊時機由外部決定
   */
  shoot() {
      const bullet = databus.pool.getItemByClass('bullet', Bullet);
      bullet.init(
          this.x + this.width / 2 - bullet.width / 2,
          this.y + 10,
          this[__.speed] + 5
      );

      databus.bullets.push(bullet);
  }
}

接下來,在 js/main.js 中加入敵機的射擊邏輯,敵機移動5次、60次時設計。


// 其他代碼...
 let ctx = canvas.getContext("2d");
 let databus = new DataBus();

const ENEMY_SPEED = 6;
// 其他代碼...

    /**
     * 隨著幀數(shù)變化的敵機生成邏輯
     * 幀數(shù)取模定義成生成的頻率
     */
    enemyGenerate(playerLevel) {
        if (databus.frame % 60 === 0) {
            let enemy = databus.pool.getItemByClass("enemy", Enemy);
            enemy.init(ENEMY_SPEED);
            databus.enemys.push(enemy);
        }
    }

// 其他代碼...

    // 實現(xiàn)游戲幀循環(huán)
    loop() {
        databus.frame++;

        this.update();
        this.render();

        if (databus.frame % 20 === 0) {
            this.player.shoot();
            this.music.playShoot();
        }

        databus.enemys.forEach(enemy => {
            const enemyShootPositions = [
                -enemy.height + ENEMY_SPEED * 5,
                -enemy.height + ENEMY_SPEED * 60
            ];
            if (enemyShootPositions.indexOf(enemy.y) !== -1) {
                enemy.shoot();
                this.music.playShoot();
            }
        });

        // 游戲結束停止幀循環(huán)
        if (databus.gameOver) {
            this.touchHandler = this.touchEventHandler.bind(this);
          canvas.addEventListener("touchstart", this.touchHandler);
            this.gameinfo.renderGameOver(ctx, databus.score);

            return;
        }

        window.requestAnimationFrame(this.loop.bind(this), canvas);
    }

這時候我們發(fā)現(xiàn),由于不明宇宙的干擾射線的影響,玩家和敵機的子彈不受控制的亂飛。接下來我們就來恢復世界的秩序吧 ;

經(jīng)偵測發(fā)現(xiàn)是對象池 pool 的獲取邏輯問題導致子彈不受控問題,我們需要區(qū)分獲取玩家、每個敵機的子彈

首先,對象獲取我們加入對象屬性的判斷,當有傳入對象屬性時,我們獲取所有屬性值一致的已回收對象,若沒有找到或者對象池為空時,則用屬性創(chuàng)建新對象


/**
   * 根據(jù)傳入的對象標識符,查詢對象池
   * 對象池為空創(chuàng)建新的類,否則從對象池中取
   */
  getItemByClass(name, className, properties) {
    let pool = this.getPoolBySign(name)

    if (pool.length === 0) return new className(properties);
   
    if (!properties) return pool.shift();
   
    const index = pool.findIndex(item => {
        return Object.keys(properties).every(property => {
            return item[property] === properties[property];
        });
    });
    return index !== -1 ? pool.splice(index, 1)[0] : new className(properties)
  }

相應的我們需要給每個子彈設置歸屬,在 js/player/bullet.js 中 Bullet 類修改 constructor


export default class Bullet extends Sprite {
    constructor({ direction, owner } = { direction: 'up' }) {
        super(direction === 'up' ? BULLET_IMG_SRC : BULLET_DOWN_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT)

        this.direction = direction;

        this.owner = owner;
    }

接著修改 js/player/index.js 的 shoot ,為其中創(chuàng)建的 bullets 提供歸屬


/**
     * 玩家射擊操作
     * 射擊時機由外部決定
     */
    shoot() {
      for(let i = 0; i < this.level; i++) {
        const bullet = databus.pool.getItemByClass('bullet', Bullet, { direction: 'up', owner: this });

同樣處理 js/npc/enemy.js 的 shoot


/**
   * 敵機射擊操作
   * 射擊時機由外部決定
   */
  shoot() {
      const bullet = databus.pool.getItemByClass('bullet', Bullet, { direction: 'down', owner: this });

最后處理 js/databus.js 中 removeBullets 的回收邏輯


/**
   * 回收子彈,進入對象池
   * 此后不進入幀循環(huán)
   */
  removeBullets(bullet) {
    const index = this.bullets.findIndex(b => b === bullet);

    bullet.visible = false

    this.bullets.splice(index, 1);

    this.pool.recover('bullet', bullet)
  }
}

這時候敵我的子彈就恢復正常了。不過這時候玩家中彈并不會死亡,現(xiàn)在來讓玩家 Go Die吧。在 js/main.js 的 collisionDetection 我們判斷增加每一顆子彈如果是敵方的,就判斷其是否打中玩家,是則游戲結束。玩家的子彈判斷保持不變。


// 全局碰撞檢測
    collisionDetection() {
        let that = this;

        databus.bullets.forEach(bullet => {
            for (let i = 0, il = databus.enemys.length; i < il; i++) {
                let enemy = databus.enemys[i];
                if (bullet.owner instanceof Enemy) {
                    databus.gameOver = this.player.isCollideWith(bullet);
                } else if (!enemy.isPlaying && enemy.isCollideWith(bullet)) {
                    enemy.playAnimation();
                    that.music.playExplosion();

                    bullet.visible = false;
                    databus.score += 1;

                    break;
                }
            }
        });

到此整個簡單改造計劃就結束了,以后還可以添加武器系統(tǒng),boss戰(zhàn)等等。下面是改造后的游戲動圖錄屏

 


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/24177.html 復制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×