首先,我们先来了解一下Weapon对象:Weapon对象也可以称为Weapon插件,它提供了快速创建和管理子弹池的能力。
武器(Weapons)射击出子弹(Phaser.Bullet对象),这些子弹实际上是有一些额外属性的sprite对象,并且这些子弹还支持Arcade物理引擎,不过暂时不支持P2引擎。
所有的子弹都被创建在一个叫Weapon.bullets的组(group)中,所以组对象支持的属性和方法,子弹组也都支持。
子弹还可以有自己的纹理和动画,你也可以控制它的射击频率、移动速度、射击角度等等属性,甚至你还可以给它们添加重力。
上面的内容几乎都是官网的翻译,下面我们先来看下面的代码,如果快速地创建一个会射击的小飞机:
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
//加载素材:子弹和飞机
game.load.image('bullet', 'assets/sprites/bullet.png');
game.load.image('ship', 'assets/sprites/shmup-ship.png');
}
var sprite;
var weapon;
var cursors;
var fireButton;
function create() {
// 创建一颗子弹,使用bullet皮肤
weapon = game.add.weapon(1, 'bullet');
//当子弹超出窗口时自动销毁
weapon.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
//因为子弹的图片是横着的,所以要旋转一下角度
weapon.bulletAngleOffset = 90;
//子弹的速度/每秒钟位移的像素值
weapon.bulletSpeed = 400;
sprite = this.add.sprite(320, 500, 'ship');
game.physics.arcade.enable(sprite);
//告诉Weapon子弹的轨迹:横向14px(小飞机宽28px),纵向0px
weapon.trackSprite(sprite, 14, 0);
//启用方向键
cursors = this.input.keyboard.createCursorKeys();
//定义空格键为射击按键
fireButton = this.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
}
function update() {
//初始化速度为0
sprite.body.velocity.x = 0;
//按下左方向键时速度为-200(左移),按下右方向键时速度为200(右移)
if (cursors.left.isDown)
{
sprite.body.velocity.x = -200;
}
else if (cursors.right.isDown)
{
sprite.body.velocity.x = 200;
}
//按下空格键时,开火
if (fireButton.isDown)
{
weapon.fire();
}
}
function render() {
weapon.debug();
}
这个例子中,我们创建了一个会射击的小飞机,它只能左右移动,并且它每次只能发射一颗子弹,如果你担心它的子弹数量太少,那么修改下weapon = game.add.weapon(1, 'bullet');的数量即可,这个数量其实是子弹池的数量,同时也意味着同一时间屏幕上最多有这个数量的子弹数。
上面的例子中,窗口中只有一颗子弹未免太单调了,不仅如此,子弹的颜色也太单一了,下面我们就再来看一个例子来熟悉weapon的各种属性:var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('ship', 'assets/sprites/thrust_ship.png');
//这张图片长宽为320*4px,截取为4x4px一共有80个画面
game.load.spritesheet('bullet', 'assets/sprites/rgblaser.png', 4, 4);
}
var sprite;
var weapon;
var cursors;
var fireButton;
function create() {
//创建40颗子弹
weapon = game.add.weapon(40, 'bullet');
//加载时已经说过,截取图片中4x4像素为一个画面
//第三个参数true告诉weapon类每次优先使用下一个画面,如果是false只会使用第一个画面
//子弹发射时,80个画面全面使用完后从0开始
weapon.setBulletFrames(0, 80, true);
//下面这个参数相当于setBulletFrames函数的第三个参数
//weapon.bulletFrameCycle = true;
//子弹销毁方式
weapon.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
//weapon.bulletKillType = Phaser.Weapon.KILL_NEVER;
//子弹速度
weapon.bulletSpeed = 400;
//射击频率(多少毫秒射击一次)
weapon.fireRate = 50;
//子弹超出边界时,会从边界的另一侧出现
//weapon.bulletWorldWrap = true;
sprite = this.add.sprite(400, 300, 'ship');
sprite.anchor.set(0.5);
game.physics.arcade.enable(sprite);
//最大速度和减速设定
sprite.body.drag.set(70);
sprite.body.maxVelocity.set(200);
//设置子弹轨迹,因为sprite.anchor已经设置为0.5,所以x方向不用位移了
weapon.trackSprite(sprite, 0, 0, true);
cursors = this.input.keyboard.createCursorKeys();
fireButton = this.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
//自动射击
// weapon.autofire = true;
}
function update() {
if (cursors.up.isDown)
{
//旋转加速度(先这么翻译吧,有点复杂)
game.physics.arcade.accelerationFromRotation(sprite.rotation, 300, sprite.body.acceleration);
}
else
{
//加速度设置为0
sprite.body.acceleration.set(0);
}
if (cursors.left.isDown)
{
//角速度=-300(旋转速度)
sprite.body.angularVelocity = -300;
}
else if (cursors.right.isDown)
{
sprite.body.angularVelocity = 300;
}
else
{
sprite.body.angularVelocity = 0;
}
if (fireButton.isDown)
{
weapon.fire();
}
//是否换向显示
game.world.wrap(sprite, 16);
}
function render() {
weapon.debug();
}
看过了两个例子,我们大概就知道了其中几个属性的含义了,不过还是要强调一下:
bulletSpeed:子弹初速度(移动速度)。
fireRate:射击频率(子弹出现的频率,单位毫秒,即多少毫秒出现一颗子弹)。
trackSprite:上面已经说过,子弹的偏移量。
autofire:这个简单,是否自动发射子弹。
sprite.body.drag.set(70):API的翻译太过绕口,你直接理解成刹车速度就行,也就是停止时的速度减小量(每秒),这是一个{Phaser.Point}对象(和scale、anchor等一样),方法接收两个参数,比如这里只写了一个,其实也等于sprite.body.drag.set(70,70),之前没有讲到这个,这里补充下。
sprite.body.maxVelocity.set(200):(小飞机)最大速度设定。
angularVelocity:角速度,每秒旋转的角度。
上面的代码只是发射一颗子弹,如果你想一次发射多颗子弹,也是可以的,只不过这些子弹还是直线弹道,虽然单个子弹可以设置便宜角度,但是没有办法像散弹枪一样,发射扇形的子弹(我研究了两个小时,在不修改源码的情况下没有办法实现,希望以后有这个功能吧),发射多颗子弹的代码也很简单,看下面的代码:var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('bullet', 'assets/bullets/bullet198.png');
game.load.image('ship', 'assets/sprites/shmup-ship.png');
}
var sprite;
var weapon;
var cursors;
var fireButton;
var bulletPositions;
function create() {
//定义48颗子弹
weapon = game.add.weapon(6*8, 'bullet');
weapon.bulletKillType = Phaser.Weapon.KILL_LIFESPAN;
//子弹寿命,和上一条设定的Phaser.Weapon.KILL_LIFESPAN配合使用
weapon.bulletLifespan = 2000;
//子弹速度及角度(因为子弹会被横着绘制,所以需要设置角度便宜)
weapon.bulletAngleOffset = 90;
weapon.bulletSpeed = 400;
//子弹随机角度
// weapon.bulletAngleVariance = 20;
sprite = this.add.sprite(320, 500, 'ship');
game.physics.arcade.enable(sprite);
//偏移量设置
weapon.trackSprite(sprite, 14, 0);
weapon.fireRate = 250;
//开启多发
weapon.multiFire = true;
cursors = this.input.keyboard.createCursorKeys();
fireButton = this.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
bulletPositions = [
{ x: 0, y: -32 },
{ x: -16, y: -16 },
{ x: 16, y: -16 },
{ x: -32, y: 0 },
{ x: 0, y: 0 },
{ x: 32, y: 0 }
];
}
function update() {
sprite.body.velocity.x = 0;
if (cursors.left.isDown)
{
sprite.body.velocity.x = -200;
}
else if (cursors.right.isDown)
{
sprite.body.velocity.x = 200;
}
if (fireButton.isDown)
{
//每次射击发射6颗子弹
weapon.fireMany(bulletPositions);
}
}
function render() {
weapon.debug();
}
步骤其实很简单,创建多颗子弹,开启多发,设定各个子弹的偏移量,然后就OK了,是不是很简单?
还有一个属性需要了解下,就是weapon的bulletAngleVariance属性,我在上面的代码中也注释过了,它给所有的子弹提供了一个随机的发射角度,而且每次刷新都是相对于当前的位置随机的,所以会出现一条随机的弹道,只是很遗憾,我还是没有找到在不修改源代码的情况下发射扇形子弹的方法。
好吧,这一节就这样了,教程阅读到这里,游戏页面的制作流程和方法大家也都熟悉了,那么下一节让我们进入实战吧,也是这个教程系列的最后一节,模拟经典游戏:雷电。