Weapon.multiFire is a new property that allows you to set a Weapon as being allowed to call fire as many times as you like, per game loop. This allows a single Weapon instance to fire multiple bullets.

Weapon.fire has two new arguments: `offsetX` and `offsetY`. If the bullet is fired from a tracked Sprite or Pointer, or the `from` argument is set, this applies a horizontal and vertical offset from the launch position.

Weapon.fireOffset attempts to fire a single Bullet from a tracked Sprite or Pointer, but applies an offset to the position first. This is a shorter form of calling `Weapon.fire` and passing in the offset arguments.

Weapon.fireMany attempts to fire multiple bullets from the positions defined in the given array. If you provide a `from` argument, or if there is a tracked Sprite or Pointer, then the positions are treated as __offsets__ from the given objects position. If `from` is undefined, and there is no tracked object, then the bullets are fired from the given positions, as they exist in the world.
This commit is contained in:
Richard Davey 2016-09-08 01:41:22 +01:00
parent 8a78029e2b
commit c42c447bfb
3 changed files with 181 additions and 14 deletions

View file

@ -309,14 +309,16 @@ You can read all about the philosophy behind Lazer [here](http://phaser.io/news/
### New Features
*
*
* Weapon.multiFire is a new property that allows you to set a Weapon as being allowed to call `fire` as many times as you like, per game loop. This allows a single Weapon instance to fire multiple bullets.
* Weapon.fire has two new arguments: `offsetX` and `offsetY`. If the bullet is fired from a tracked Sprite or Pointer, or the `from` argument is set, this applies a horizontal and vertical offset from the launch position.
* Weapon.fireOffset attempts to fire a single Bullet from a tracked Sprite or Pointer, but applies an offset to the position first. This is a shorter form of calling `Weapon.fire` and passing in the offset arguments.
* Weapon.fireMany attempts to fire multiple bullets from the positions defined in the given array. If you provide a `from` argument, or if there is a tracked Sprite or Pointer, then the positions are treated as __offsets__ from the given objects position. If `from` is undefined, and there is no tracked object, then the bullets are fired from the given positions, as they exist in the world.
*
### Updates
* TypeScript definitions fixes and updates (thanks )
* Docs typo fixes (thanks @JTronLabs)
* TypeScript definitions fixes and updates (thanks @chriteixeira)
* Docs typo fixes (thanks @JTronLabs @samme)
* `Phaser.Line.fromSprite` now uses the Sprite.centerX and centerY properties if the `useCenter` argument is true. Before it required you to have overridden the Sprite and added the property yourself (thanks @samme #2729)
*
*

View file

@ -340,6 +340,24 @@ Phaser.Weapon = function (game, parent) {
*/
this.trackedPointer = null;
/**
* If you want this Weapon to be able to fire more than 1 bullet in a single
* update, then set this property to `true`. When `true` the Weapon plugin won't
* set the shot / firing timers until the `postRender` phase of the game loop.
* This means you can call `fire` (and similar methods) as often as you like in one
* single game update.
*
* @type {boolean}
*/
this.multiFire = false;
/**
* Internal multiFire test flag.
*
* @type {boolean}
*/
this._hasFired = false;
/**
* If the Weapon is tracking a Sprite, should it also track the Sprites rotation?
* This is useful for a game such as Asteroids, where you want the weapon to fire based
@ -367,6 +385,14 @@ Phaser.Weapon = function (game, parent) {
*/
this._nextFire = 0;
/**
* Internal firing rate time tracking variable used by multiFire.
*
* @type {number}
* @private
*/
this._tempNextFire = 0;
/**
* Internal firing rotation tracking point.
*
@ -623,6 +649,25 @@ Phaser.Weapon.prototype.update = function () {
};
/**
* Internal update method, called by the PluginManager.
*
* @method Phaser.Weapon#postRender
* @protected
*/
Phaser.Weapon.prototype.postRender = function () {
if (!this.multiFire || !this._hasFired)
{
return;
}
this._hasFired = false;
this._nextFire = this._tempNextFire;
};
/**
* Sets this Weapon to track the given Sprite, or any Object with a public `world` Point object.
* When a Weapon tracks a Sprite it will automatically update its `fireFrom` value to match the Sprites
@ -688,6 +733,87 @@ Phaser.Weapon.prototype.trackPointer = function (pointer, offsetX, offsetY) {
};
/**
* Attempts to fire multiple bullets from the positions defined in the given array.
*
* If you provide a `from` argument, or if there is a tracked Sprite or Pointer, then
* the positions are treated as __offsets__ from the given objects position.
*
* If `from` is undefined, and there is no tracked object, then the bullets are fired
* from the given positions, as they exist in the world.
*
* Calling this method sets `Weapon.multiFire = true`.
*
* If there are not enough bullets available in the pool, and the pool cannot be extended,
* then this method may not fire from all of the given positions.
*
* When the bullets are launched they have their texture and frame updated, as required.
* The velocity of the bullets are calculated based on Weapon properties like `bulletSpeed`.
*
* @method Phaser.Weapon#fireMany
* @param {array} positions - An array of positions. Each position can be any Object, as long as it has public `x` and `y` properties, such as Phaser.Point, { x: 0, y: 0 }, Phaser.Sprite, etc.
* @param {Phaser.Sprite|Phaser.Point|Object|string} [from] - Optionally fires the bullets **from** the `x` and `y` properties of this object, _instead_ of any `Weapon.trackedSprite` or `trackedPointer` that is set.
* @return {array} An array containing all of the fired Phaser.Bullet objects, if a launch was successful, otherwise an empty array.
*/
Phaser.Weapon.prototype.fireMany = function (positions, from) {
this.multiFire = true;
var bullets = [];
var _this = this;
if (from || this.trackedSprite || this.trackedPointer)
{
positions.forEach(function(offset) {
bullets.push(_this.fire(from, null, null, offset.x, offset.y));
});
}
else
{
positions.forEach(function(position) {
bullets.push(_this.fire(position));
});
}
return bullets;
};
/**
* Attempts to fire a single Bullet from a tracked Sprite or Pointer, but applies an offset
* to the position first. This is the same as calling `Weapon.fire` and passing in the offset arguments.
*
* If there are no more bullets available in the pool, and the pool cannot be extended,
* then this method returns `null`. It will also return `null` if not enough time has expired since the last time
* the Weapon was fired, as defined in the `Weapon.fireRate` property.
*
* Otherwise the first available bullet is selected, launched, and returned.
*
* When the bullet is launched it has its texture and frame updated, as required. The velocity of the bullet is
* calculated based on Weapon properties like `bulletSpeed`.
*
* If you wish to fire multiple bullets in a single game update, then set `Weapon.multiFire = true`
* and you can call this method as many times as you like, per loop. See also `Weapon.fireMany`.
*
* @method Phaser.Weapon#fireOffset
* @param {number} [offsetX=0] - The horizontal offset from the position of the tracked Sprite or Pointer, as set with `Weapon.trackSprite`.
* @param {number} [offsetY=0] - The vertical offset from the position of the tracked Sprite or Pointer, as set with `Weapon.trackSprite`.
* @return {Phaser.Bullet} The fired bullet, if a launch was successful, otherwise `null`.
*/
Phaser.Weapon.prototype.fireOffset = function (offsetX, offsetY) {
if (offsetX === undefined) { offsetX = 0; }
if (offsetY === undefined) { offsetY = 0; }
return this.fire(null, null, null, offsetX, offsetY);
};
/**
* Attempts to fire a single Bullet. If there are no more bullets available in the pool, and the pool cannot be extended,
* then this method returns `null`. It will also return `null` if not enough time has expired since the last time
@ -703,13 +829,22 @@ Phaser.Weapon.prototype.trackPointer = function (pointer, offsetX, offsetY) {
* When the bullet is launched it has its texture and frame updated, as required. The velocity of the bullet is
* calculated based on Weapon properties like `bulletSpeed`.
*
* If you wish to fire multiple bullets in a single game update, then set `Weapon.multiFire = true`
* and you can call `fire` as many times as you like, per loop. Multiple fires in a single update
* only counts once towards the `shots` total, but you will still receive a Signal for each bullet.
*
* @method Phaser.Weapon#fire
* @param {Phaser.Sprite|Phaser.Point|Object} [from] - Optionally fires the bullet **from** the `x` and `y` properties of this object. If set this overrides `Weapon.trackedSprite` or `trackedPointer`. Pass `null` to ignore it.
* @param {number} [x] - The x coordinate, in world space, to fire the bullet **towards**. If left as `undefined` the bullet direction is based on its angle.
* @param {number} [y] - The y coordinate, in world space, to fire the bullet **towards**. If left as `undefined` the bullet direction is based on its angle.
* @param {Phaser.Sprite|Phaser.Point|Object|string} [from] - Optionally fires the bullet **from** the `x` and `y` properties of this object. If set this overrides `Weapon.trackedSprite` or `trackedPointer`. Pass `null` to ignore it.
* @param {number} [x] - The x coordinate, in world space, to fire the bullet **towards**. If left as `undefined`, or `null`, the bullet direction is based on its angle.
* @param {number} [y] - The y coordinate, in world space, to fire the bullet **towards**. If left as `undefined`, or `null`, the bullet direction is based on its angle.
* @param {number} [offsetX=0] - If the bullet is fired from a tracked Sprite or Pointer, or the `from` argument is set, this applies a horizontal offset from the launch position.
* @param {number} [offsetY=0] - If the bullet is fired from a tracked Sprite or Pointer, or the `from` argument is set, this applies a vertical offset from the launch position.
* @return {Phaser.Bullet} The fired bullet, if a launch was successful, otherwise `null`.
*/
Phaser.Weapon.prototype.fire = function (from, x, y) {
Phaser.Weapon.prototype.fire = function (from, x, y, offsetX, offsetY) {
if (x === undefined) { x = null; }
if (y === undefined) { y = null; }
if (this.game.time.now < this._nextFire || (this.fireLimit > 0 && this.shots === this.fireLimit))
{
@ -784,13 +919,23 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
}
}
if (offsetX !== undefined)
{
this.fireFrom.x += offsetX;
}
if (offsetY !== undefined)
{
this.fireFrom.y += offsetY;
}
var fromX = (this.fireFrom.width > 1) ? this.fireFrom.randomX : this.fireFrom.x;
var fromY = (this.fireFrom.height > 1) ? this.fireFrom.randomY : this.fireFrom.y;
var angle = (this.trackRotation) ? this.trackedSprite.angle : this.fireAngle;
// The position (in world space) to fire the bullet towards, if set
if (x !== undefined && y !== undefined)
if (x !== null && y !== null)
{
angle = this.game.math.radToDeg(Math.atan2(y - fromY, x - fromX));
}
@ -895,6 +1040,8 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
bullet.body.velocity.set(moveX, moveY);
bullet.body.gravity.set(this.bulletGravity.x, this.bulletGravity.y);
var next = 0;
if (this.bulletSpeedVariance !== 0)
{
var rate = this.fireRate;
@ -906,14 +1053,29 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
rate = 0;
}
this._nextFire = this.game.time.now + rate;
next = this.game.time.now + rate;
}
else
{
this._nextFire = this.game.time.now + this.fireRate;
next = this.game.time.now + this.fireRate;
}
this.shots++;
if (this.multiFire)
{
if (!this._hasFired)
{
// We only add 1 to the 'shots' count for multiFire shots
this._hasFired = true;
this._tempNextFire = next;
this.shots++;
}
}
else
{
this._nextFire = next;
this.shots++;
}
this.onFire.dispatch(bullet, this, speed);

View file

@ -1,7 +1,7 @@
/// <reference path="pixi.d.ts" />
/// <reference path="p2.d.ts" />
// Type definitions for Phaser 2.6.2 - 26th August 2016
// Type definitions for Phaser 3.0.0 - 7th September 2016
// Project: https://github.com/photonstorm/phaser
declare module "phaser" {
@ -5636,6 +5636,7 @@ declare module Phaser {
fireLimit: number;
fireRate: number;
fireRateVariance: number;
multiFire: boolean;
onFire: Phaser.Signal;
onFireLimit: Phaser.Signal;
onKill: Phaser.Signal;
@ -5651,10 +5652,12 @@ declare module Phaser {
createBullets(quantity?: number, key?: any, frame?: any, group?: Phaser.Group): Phaser.Weapon;
debug(x?: number, y?: number, debugBodies?: boolean): void;
destroy(): void;
fire(from?: any, x?: number, y?: number): Phaser.Bullet;
fire(from?: any, x?: number, y?: number, offsetX?: number, offsetY?: number): Phaser.Bullet;
fireAtPointer(pointer: Phaser.Pointer): Phaser.Bullet;
fireAtSprite(sprite: Phaser.Sprite): Phaser.Bullet;
fireAtXY(x: number, y: number): Phaser.Bullet;
fireMany(positions: any[], from?: any): Phaser.Bullet[];
fireOffset(offsetX?: number, offsetY?: number): Phaser.Bullet;
forEach(callback: any, callbackContext: any): Phaser.Weapon;
killAll(): Phaser.Weapon;
pauseAll(): Phaser.Weapon;