微信小游戏体验的飞机改造计划
微信游戏已经上线好几天了。不用说,这个功能对小程序和小游戏推广的影响可以很快提高。如何开发官方文档已经解释过了,这个是官方飞机演示的小修改。
开发预备式
下载微信开发者工具最新版本(v1.02.1712280)根据官方文件,目前没有公开注册。所以目前只能用无AppID模式进行体验。为了让HTML5游戏易于访问,官方提供了一个Adapter。这个功能是为HTML5和wx提供一个全局的翻译层。
打飞机小游戏
你可以在创建一个没有AppID模式的微信小游戏后看到官方演示,里面的入口文件和配置文件是game.js和game.json Game.js介绍并初始化main.js,里面包含了整个飞机格斗游戏场景的主要功能、参与者(玩家飞机和敌人飞机)以及游戏逻辑。在main.js中,我们可以发现由于Adapter的存在,这里的代码和我们平时的代码编写没有什么区别。游戏的主要逻辑如下:
在循环中,玩家每20帧拍摄一次,每60帧生成新的敌机。每一帧,检查玩家和敌机是否死亡。玩家死亡游戏结束,敌机死亡分数为1。只有玩家才能射击,射击方式固定,躲避敌机才能生存。接下来,我们将改造这些,以提高游戏的可玩性和挑战性。
玩家升级计划
玩家初始等级为1。玩家可以通过杀死敌机来升级。每次击落30架敌机,玩家都会升级一次。如果增加一个射击孔,玩家最多升级两次。首先,用编辑器打开player/index.js,将级别逻辑添加到player的类中。
导出默认类PLAYER扩展Sprite { constructor(){ super(Player _ IMG _ SRC,PLAYER_WIDTH,PLAYER_HEIGHT) //默认情况下,Player位于屏幕底部的中心位置这一点。x=屏幕宽度/2-这个。宽度/2这是。y=屏幕高度-这个。高度-30//用于识别手指移动时手指是否已经在平面上。感动=假这。项目符号=[]//初始化事件以监控此。initevent()这。玩家等级=1;} get level(){ return this . PlayLevel;}设置级别(level){ this . player level=math . min(level,3);}
round-color:="" helvetica="" microsoft="">接下来在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 = 16const BULLET_HEIGHT = 30const __ = { 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战等等。下面是改造后的游戏动图录屏
版权声明:微信小游戏体验的飞机改造计划是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。