写在前面
该飞机大战素材来源于phaser小站:
www.phaser-china.com/tutorial-de…
原文使用phaser2进行实现,本文用phaser3将飞机大战重构一遍,在实战中学习一下phaser3的api
源码:github.com/YUPENG12138…
1、初始化项目
1.我们使用github上初始化phaser3的webpack工程模板
github.com/photonstorm…
2.将项目中的phaser3版本更新到最新,npm i phaser3 -S
3.将MP3文件的处理引入webpack
// plane/webpack/base.js
{
test: /\.(gif|png|jpe?g|svg|xml|mp3)$/i,
use: "file-loader"
}
4.将项目中使用到的素材放到assets文件夹中
5.写个node脚本,生成一下静态资源的对应映射关系。
plane/assets_script.js
const fs = require('fs');;
const path = require('path');
const assetsList = fs.readdirSync(path.resolve(__dirname, 'src/assets/'));
const asssetsMap = {};
assetsList.forEach((item) => {
const key = item.match(/.\w+/)[0];
Object.assign(asssetsMap, {
[key]: `assets/${item}`,
});
});
fs.writeFileSync(path.resolve(__dirname, 'src/asset_map.json'), JSON.stringify(asssetsMap));
plane\src\asset_map.json
2、初始化配置,加载资源,设置背景
// 引入phaser
import Phaser from 'phaser';
//将资源映射map引进来
const assetsMap = require('./asset_map.json');
/*
* 这里是phaser初始化时的配置项
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Types.Core.html#.GameConfig
* type 表示使用哪个渲染器,canvas,还是webgl。AUTO会自动选择,也可以设置
* width,height画布宽高
* scene 项目中的场景,是一个场景还是多个场景,preload create update相当于该场景的生命周期
* /
const config = {
type: Phaser.AUTO,
width: 240,
height: 400,
scene: {
preload,
create,
update,
},
};
// 配置完成后使用new Phaser.Game(config)实例化游戏。
// api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Game.html
const game = new Phaser.Game(config);
/*
* 将静态资源使用this.load.image引入到项目中
* 这里有个问题,刚开始做的时候没有考虑到精灵图,普通图片和MP3的引用方式不一致的问题,都按照image的方式引入进来了
* 后面先做了兼容处理,等后续再优化
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Loader.LoaderPlugin.html
*/
const asset = {};
function preload() {
for (const key in assetsMap) {
if (assetsMap.hasOwnProperty(key)) {
asset[key] = this.load.image(key, require(`./${assetsMap[key]}`));
}
}
}
/*
* 资源加载完成后,在create里将背景图片引入进来
* this.add.image(x, y, imageKey)
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.GameObjectFactory.html#image__anchor
* phaser3默认位置点为中心点,所以为了从左上角设置位置,我们使用setOrigin(x, y)设置它的起始位置
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Components.Origin.html#setOrigin__anchor
*/
function create() {
const bg = this.add.image(0, 0, 'bg');
bg.setOrigin(0, 0);
}
function update() {
}
这样游戏的背景就加载好了:
3、设置游戏资源加载进度,加载完成后,从加载场景切换到游戏开始场景
import Phaser from 'phaser';
const assetsMap = require('./asset_map.json');
/*
* 这里我们设置一个gameSenceCenter变量存放各个游戏场景
* 设置一个boot用于加载资源,start为游戏开始场景
*/
const gameSenceCenter = {};
gameSenceCenter.boot = {
key: 'boot',
preload() {
for (const key in assetsMap) {
if (assetsMap.hasOwnProperty(key)) {
assetsMap[key] = this.load.image(key, require(`./${assetsMap[key]}`));
}
}
/*
* 这里我们添加一个文本来显示进度
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.GameObjectCreator.html#text__anchor
*/
const percentText = this.make.text({
x: this.game.config.width / 2,
y: this.game.config.height / 2 - 5,
text: '0%',
style: {
font: '18px monospace',
fill: '#ffffff'
}
})
.setOrigin(0.5, 0.5);
/*
* 使用this.load.on监听加载进度和完成状态
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Loader.LoaderPlugin.html#on__anchor
* 使用setText()设置文本显示
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Text.html#setText__anchor
*/
this.load.on('progress', function (value) {
percentText.setText(parseInt(value * 100) + '%');
});
this.load.on('complete', function () {
percentText.destroy();
});
},
create() {
// 在加载完成后调用this.scene.start(场景key)开始下一个场景
// api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Scenes.ScenePlugin.html#start__anchor)
this.scene.start('start');
},
update() {}
}
gameSenceCenter.start = {
key: 'start',
create() {
this.add.image(0,0,'bg').setOrigin(0);
},
update() {},
}
const config = {
type: Phaser.AUTO,
width: 240,
height: 400,
scene: [gameSenceCenter.boot, gameSenceCenter.start],
};
const game = new Phaser.Game(config);
4、手机屏幕适配
// plane/index.html
<!--设置一下通用样式-->
<style>
* {
margin: 0;
padding: 0;
}
</style>
// plane/src/index.js
/*
* 在boot preload中设置适配兼容,desktop表示是否是桌面端
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Game.html#device__anchor
* Phaser.Scale.FIT 表示保持比例将界面充满,还有其他的属性可以看文档去尝试一下
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Scale.ScaleManager.html#scaleMode__anchor
* 设置后需要刷新一下
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Scale.ScaleManager.html#refresh__anchor
*/
if (!this.game.device.os.desktop) {
this.scale.scaleMode = Phaser.Scale.FIT;
this.scale.refresh();
}
这样就充满手机屏幕了
5、为开始场景添加元素
1、这里我们要修改一下boot.preload函数里的加载逻辑,做下前面说的精灵图加载兼容,精灵图和正常图片的加载方式是不一样的
这里我们先用到了飞机和开始按钮,就先处理这两个
/*
* 加载精灵图的方法是this.load.spritesheet(图片key, 图片路径, { 每帧宽度, 每帧高度 });
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Loader.LoaderPlugin.html#spritesheet__anchor
*/
preload() {
for (const key in assetsMap) {
if (assetsMap.hasOwnProperty(key)) {
if (key === 'myplane') {
this.load.spritesheet(key, require(`./${assetsMap[key]}`), {
frameWidth: 40,
frameHeight: 40,
});
continue;
}
if (key === 'startbutton') {
this.load.spritesheet(key, require(`./${assetsMap[key]}`), {
frameWidth: 100,
frameHeight: 40,
});
continue;
}
assetsMap[key] = this.load.image(key, require(`./${assetsMap[key]}`));
}
}
...
}
2、我们开始为start场景加元素
/*
* 在start.create中我们添加元素逻辑
* 1.在start场景中我们添加游戏背景
*
* 2.添加copyright标识
*
* 3.添加飞机精灵
* this.add.sprite(x, y, 图片key),因为引入时候我们是用spritesheet引入的,所以会显示第一帧
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.GameObjectFactory.html#sprite__anchor
*
* 4.创建飞机帧动画
* this.animas.create({动画的名字, 序列帧, 帧速率, 重复状态})
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Types.Animations.html#.Animation
* this.anims.generateFrameNumbers() 生成一个Phaser.Types.Animations.AnimationFrame对象数组
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.Animations.AnimationManager.html#generateFrameNames__anchor
*
* 5.plane.anims.play('fly');让精灵调用帧动画进行播放
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Components.Animation.html#play__anchor
*
* 6.添加开始按钮
* 这里涉及到了this.add.sprite的第4个参数,表示要加载精灵图里的第几帧,从0开始
* setInteractive()是将精灵变成可点击的状态
* https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Sprite.html#setInteractive__anchor
*
* 7.为开始按钮添加按下和抬起事件
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Sprite.html#on__anchor
* 在按下抬起是使用setFrame去切换帧
* api链接:https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Sprite.html#setFrame__anchor
*/
// 添加背景
const bg = this.add.image(0, 0, 'bg').setOrigin(0);
// 添加游戏copyright标识
this.add.image(this.game.config.width / 2, this.game.config.height - 16, 'copyright');
// 引入飞机精灵
const plane = this.add.sprite(this.game.config.width / 2, 100, 'myplane');
// 创建飞行帧动画
this.anims.create({
key: 'fly',
frames: this.anims.generateFrameNumbers('myplane', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
// 飞机调用飞行动画
plane.anims.play('fly');
// 添加开始按钮
const startButton = this.add.sprite(this.game.config.width / 2, 200, 'startbutton', 1).setInteractive();
startButton.on('pointerdown', () => {
startButton.setFrame(0);
})
startButton.on('pointerup', () => {
startButton.setFrame(1);
console.log('start game');
})
本篇就先到这里,下周会更新游戏场景的部分逻辑,包含飞机拖拽,边界检测,发射子弹,敌机碰撞检测。