摘要:微信小游戲推出已有幾天了,這個功能對小程序和小游戲的推動影響不用多說,大家趕緊摩拳擦掌往上擼就可以了。打飛機小游戲使用無模式創建一個微信小游戲后可以看到官方,其中入口文件和配置文件和。
微信小游戲推出已有幾天了,這個功能對小程序和小游戲的推動影響不用多說,大家趕緊摩拳擦掌往上擼就可以了。關于如何開發官方文檔已經說明了,這篇則是對官方的打飛機demo一些小改造。
開發預備式下載最新版本的微信開發者工具(v1.02.1712280)
根據官方文檔說明,目前不提供公開注冊。因此目前只能使用無AppID模式進行體驗
為了讓HTML5游戲輕松接入,官方提供了Adapter。這個的作用就是提供HTML5寫法和wx寫法的全局轉換層。
打飛機小游戲使用無AppID模式創建一個微信小游戲后可以看到官方demo,其中入口文件和配置文件:game.js和game.json。game.js引入并初始化包含整個打飛機的游戲場景、參與者(玩家飛機和敵方飛機)、游戲邏輯的主函數的main.js。在main.js中我們可以發現由于Adapter的存在,這里的代碼和我們平常的代碼寫法沒什么差異了。游戲的主邏輯如下圖:
在loop中,玩家每隔20幀射一次,每隔60幀生成新的敵機。每幀檢查玩家和敵機是否死亡,玩家死亡游戲結束,敵機死亡分數+1。只有玩家可以射擊,且射擊方式固定,通過躲避敵機生存。接下來我們針對這些進行改造,提升游戲的可玩性和挑戰性。
玩家升級計劃玩家初始等級為1,玩家可通過擊殺敵機升級,每擊落30敵機升級一次
玩家每升級一次,增加一個射擊口
玩家最多升級兩次
首先用編輯器打開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 // 用于在手指移動的時候標識手指是否已經在飛機上了 this.touched = false this.bullets = [] // 初始化事件監聽 this.initEvent() this.playerLevel = 1; } get level () { return this.playerLevel; } set level (level) { this.playerLevel = Math.min(level, 3); }
接下來在main.js的update函數加入升級邏輯。
// 其他代碼... 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(); } // 其他代碼...
好的,到此玩家已經可以正常升級了。那么該給予玩家獎勵品了。在player/index.js的shoot函數中我們修改射擊的邏輯。玩家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) } } // ...其他代碼
武器的最終形態如圖, 這時候的玩家已經可以為所欲為了<_<,實際上都不需要躲避了。。。:
敵人的反擊號角為了對抗愚昧的玩家,不讓他們為所欲為,最后沒興趣玩下去~~,敵機裝備武器,反擊開始。
首先敵機的子彈是向下,所以復制一份images/bullet.png,并顛倒保存為images/bullet-down.png, 然后我們重用js/player/bullet.js,在構造函數處增加敵機的子彈配置項,并修改敵人子彈更新邏輯。
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; // 其他代碼... /** * 隨著幀數變化的敵機生成邏輯 * 幀數取模定義成生成的頻率 */ enemyGenerate(playerLevel) { if (databus.frame % 60 === 0) { let enemy = databus.pool.getItemByClass("enemy", Enemy); enemy.init(ENEMY_SPEED); databus.enemys.push(enemy); } } // 其他代碼... // 實現游戲幀循環 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(); } }); // 游戲結束停止幀循環 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); }
這時候我們發現,由于不明宇宙的干擾射線的影響,玩家和敵機的子彈不受控制的亂飛。接下來我們就來恢復世界的秩序吧 ;
經偵測發現是對象池pool的獲取邏輯問題導致子彈不受控問題,我們需要區分獲取玩家、每個敵機的子彈
首先,對象獲取我們加入對象屬性的判斷,當有傳入對象屬性時,我們獲取所有屬性值一致的已回收對象,若沒有找到或者對象池為空時,則用屬性創建新對象
/** * 根據傳入的對象標識符,查詢對象池 * 對象池為空創建新的類,否則從對象池中取 */ 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,為其中創建的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的回收邏輯
/** * 回收子彈,進入對象池 * 此后不進入幀循環 */ removeBullets(bullet) { const index = this.bullets.findIndex(b => b === bullet); bullet.visible = false this.bullets.splice(index, 1); this.pool.recover("bullet", bullet) } }
這時候敵我的子彈就恢復正常了。不過這時候玩家中彈并不會死亡,現在來讓玩家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; } } });
到此整個簡單改造計劃就結束了,以后還可以添加武器系統,boss戰等等。下面是改造后的游戲動圖錄屏
本文始發于本人的公眾號:楓之葉。公眾號二維碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90576.html
摘要:今天杭州又是大雨,被淋了個落湯雞,都怪我家大狼狗非要騎電動車,我昨天吐槽要買的帥氣的雨衣還沒有買不過大雨和飛機大戰小游戲更配哦。微信早已正式發布微信內置飛機大戰游戲,目前該游戲已經下線。此時,界面中會顯示此次玩家的飛機大戰分數。showImg(https://user-gold-cdn.xitu.io/2019/5/15/16ab9377884b99f7); 今天杭州又是大雨,被淋了個落湯雞...
摘要:今天杭州又是大雨,被淋了個落湯雞,都怪我家大狼狗非要騎電動車,我昨天吐槽要買的帥氣的雨衣還沒有買不過大雨和飛機大戰小游戲更配哦。微信早已正式發布微信內置飛機大戰游戲,目前該游戲已經下線。此時,界面中會顯示此次玩家的飛機大戰分數。 今天杭州又是大雨,被淋了個落湯雞,都怪我家大狼狗非要騎電動車,我昨天吐槽要買的帥氣的雨衣還沒有買,不過大雨和飛機大戰小游戲更配哦。 這篇文章來自我司的王老吉同...
摘要:但開發的游戲是無法通過網頁發給別人在線玩的,更不能做成微信小游戲。它使用作為開發語言,開發出的游戲可以直接生成微信小游戲網頁安卓等平臺上的版本。 微信群里最大的騷擾源有兩種: 一是轉發#吱口令#~!@#¥%……&*,長按復制此消息領紅包之類的 另一種就是各種小程序和小游戲的分享 前天有同學無意間把一個小游戲分享到了答疑群中,我看了一下,其實游戲的代碼邏輯并不復雜(簡化版的跳一跳,套上個...
閱讀 3693·2021-11-25 09:43
閱讀 2653·2021-11-25 09:43
閱讀 3850·2021-11-24 09:38
閱讀 702·2021-11-18 10:02
閱讀 2242·2021-09-22 15:53
閱讀 3002·2019-08-30 15:44
閱讀 2778·2019-08-30 14:01
閱讀 2760·2019-08-29 15:15