成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

微信小游戲體驗(yàn)之打飛機(jī)改造計(jì)劃

dongfangyiyu / 1797人閱讀

摘要:微信小游戲推出已有幾天了,這個(gè)功能對(duì)小程序和小游戲的推動(dòng)影響不用多說(shuō),大家趕緊摩拳擦掌往上擼就可以了。打飛機(jī)小游戲使用無(wú)模式創(chuàng)建一個(gè)微信小游戲后可以看到官方,其中入口文件和配置文件和。

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

開(kāi)發(fā)預(yù)備式

下載最新版本的微信開(kāi)發(fā)者工具(v1.02.1712280)

根據(jù)官方文檔說(shuō)明,目前不提供公開(kāi)注冊(cè)。因此目前只能使用無(wú)AppID模式進(jìn)行體驗(yàn)

為了讓HTML5游戲輕松接入,官方提供了Adapter。這個(gè)的作用就是提供HTML5寫法和wx寫法的全局轉(zhuǎn)換層。

打飛機(jī)小游戲

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

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

玩家升級(jí)計(jì)劃

玩家初始等級(jí)為1,玩家可通過(guò)擊殺敵機(jī)升級(jí),每擊落30敵機(jī)升級(jí)一次

玩家每升級(jí)一次,增加一個(gè)射擊口

玩家最多升級(jí)兩次

首先用編輯器打開(kāi)player/index.js,將等級(jí)邏輯加入到玩家的類中。

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

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

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

    this.bullets = []

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

    this.playerLevel = 1;
  }

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

接下來(lái)在main.jsupdate函數(shù)加入升級(jí)邏輯。

// 其他代碼...

    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)可以正常升級(jí)了。那么該給予玩家獎(jiǎng)勵(lì)品了。在player/index.jsshoot函數(shù)中我們修改射擊的邏輯。玩家1級(jí)時(shí)只有中間的射擊口,2級(jí)有左邊和中間的射擊口,3級(jí)有左中右三個(gè)射擊口。

// ...其他代碼

    /**
     * 玩家射擊操作
     * 射擊時(shí)機(jī)由外部決定
     */
    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)如圖, 這時(shí)候的玩家已經(jīng)可以為所欲為了<_<,實(shí)際上都不需要躲避了。。。:

敵人的反擊號(hào)角

為了對(duì)抗愚昧的玩家,不讓他們?yōu)樗麨?,最后沒(méi)興趣玩下去~~,敵機(jī)裝備武器,反擊開(kāi)始。

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

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結(jié)尾部分為敵人裝備武器, 子彈速度為敵人自身速度+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]

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

  /**
   * 敵機(jī)射擊操作
   * 射擊時(shí)機(jī)由外部決定
   */
  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);
  }
}

接下來(lái),在js/main.js中加入敵機(jī)的射擊邏輯,敵機(jī)移動(dòng)5次、60次時(shí)設(shè)計(jì)。

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

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

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

// 其他代碼...

    // 實(shí)現(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();
            }
        });

        // 游戲結(jié)束停止幀循環(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);
    }

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

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

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

  /**
   * 根據(jù)傳入的對(duì)象標(biāo)識(shí)符,查詢對(duì)象池
   * 對(duì)象池為空創(chuàng)建新的類,否則從對(duì)象池中取
   */
  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)
  }

相應(yīng)的我們需要給每個(gè)子彈設(shè)置歸屬,在js/player/bullet.jsBullet類修改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.jsshoot,為其中創(chuàng)建的bullets提供歸屬

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

同樣處理js/npc/enemy.jsshoot

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

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

  /**
   * 回收子彈,進(jìn)入對(duì)象池
   * 此后不進(jìn)入幀循環(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)
  }
}

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

    // 全局碰撞檢測(cè)
    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;
                }
            }
        });

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

本文始發(fā)于本人的公眾號(hào):楓之葉。公眾號(hào)二維碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90576.html

相關(guān)文章

  • 無(wú)聊嗎,寫個(gè)【飛機(jī)大戰(zhàn)】來(lái)玩吧

    摘要:今天杭州又是大雨,被淋了個(gè)落湯雞,都怪我家大狼狗非要騎電動(dòng)車,我昨天吐槽要買的帥氣的雨衣還沒(méi)有買不過(guò)大雨和飛機(jī)大戰(zhàn)小游戲更配哦。微信早已正式發(fā)布微信內(nèi)置飛機(jī)大戰(zhàn)游戲,目前該游戲已經(jīng)下線。此時(shí),界面中會(huì)顯示此次玩家的飛機(jī)大戰(zhàn)分?jǐn)?shù)。showImg(https://user-gold-cdn.xitu.io/2019/5/15/16ab9377884b99f7); 今天杭州又是大雨,被淋了個(gè)落湯雞...

    李濤 評(píng)論0 收藏0
  • 無(wú)聊嗎,寫個(gè)【飛機(jī)大戰(zhàn)】來(lái)玩吧

    摘要:今天杭州又是大雨,被淋了個(gè)落湯雞,都怪我家大狼狗非要騎電動(dòng)車,我昨天吐槽要買的帥氣的雨衣還沒(méi)有買不過(guò)大雨和飛機(jī)大戰(zhàn)小游戲更配哦。微信早已正式發(fā)布微信內(nèi)置飛機(jī)大戰(zhàn)游戲,目前該游戲已經(jīng)下線。此時(shí),界面中會(huì)顯示此次玩家的飛機(jī)大戰(zhàn)分?jǐn)?shù)。 今天杭州又是大雨,被淋了個(gè)落湯雞,都怪我家大狼狗非要騎電動(dòng)車,我昨天吐槽要買的帥氣的雨衣還沒(méi)有買,不過(guò)大雨和飛機(jī)大戰(zhàn)小游戲更配哦。 這篇文章來(lái)自我司的王老吉同...

    MSchumi 評(píng)論0 收藏0
  • 微信游戲體驗(yàn)

    摘要:前言前天一個(gè)跳一跳小游戲刷遍了朋友圈,也代表了微信小程序擁有了搭載游戲的功能早該往這方面發(fā)展了,這才是應(yīng)該有的形態(tài)嘛。作為一個(gè)前端,我的大刀早已經(jīng)饑渴難耐了,趕緊去下一波最新的微信官方開(kāi)發(fā)工具,體驗(yàn)一波小游戲要如何開(kāi)發(fā)。 本文旨在通過(guò)分析官方給出的一個(gè)飛機(jī)大戰(zhàn)小游戲的源代碼來(lái)說(shuō)明如何進(jìn)行小游戲的開(kāi)發(fā)。 1.前言 前天一個(gè)跳一跳小游戲刷遍了朋友圈,也代表了微信小程序擁有了搭載游戲的功能(...

    elina 評(píng)論0 收藏0
  • 游戲開(kāi)發(fā)上手體驗(yàn) - Cocos Creator

    摘要:但開(kāi)發(fā)的游戲是無(wú)法通過(guò)網(wǎng)頁(yè)發(fā)給別人在線玩的,更不能做成微信小游戲。它使用作為開(kāi)發(fā)語(yǔ)言,開(kāi)發(fā)出的游戲可以直接生成微信小游戲網(wǎng)頁(yè)安卓等平臺(tái)上的版本。 微信群里最大的騷擾源有兩種: 一是轉(zhuǎn)發(fā)#吱口令#~!@#¥%……&*,長(zhǎng)按復(fù)制此消息領(lǐng)紅包之類的 另一種就是各種小程序和小游戲的分享 前天有同學(xué)無(wú)意間把一個(gè)小游戲分享到了答疑群中,我看了一下,其實(shí)游戲的代碼邏輯并不復(fù)雜(簡(jiǎn)化版的跳一跳,套上個(gè)...

    zhiwei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<