Skip to content

Commit c42c447

Browse files
committed
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.
1 parent 8a78029 commit c42c447

3 files changed

Lines changed: 181 additions & 14 deletions

File tree

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,16 @@ You can read all about the philosophy behind Lazer [here](http://phaser.io/news/
309309

310310
### New Features
311311

312-
*
313-
*
312+
* 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.
313+
* 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.
314+
* 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.
315+
* 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.
314316
*
315317

316318
### Updates
317319

318-
* TypeScript definitions fixes and updates (thanks )
319-
* Docs typo fixes (thanks @JTronLabs)
320+
* TypeScript definitions fixes and updates (thanks @chriteixeira)
321+
* Docs typo fixes (thanks @JTronLabs @samme)
320322
* `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)
321323
*
322324
*

src/plugins/weapon/WeaponPlugin.js

Lines changed: 170 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,24 @@ Phaser.Weapon = function (game, parent) {
340340
*/
341341
this.trackedPointer = null;
342342

343+
/**
344+
* If you want this Weapon to be able to fire more than 1 bullet in a single
345+
* update, then set this property to `true`. When `true` the Weapon plugin won't
346+
* set the shot / firing timers until the `postRender` phase of the game loop.
347+
* This means you can call `fire` (and similar methods) as often as you like in one
348+
* single game update.
349+
*
350+
* @type {boolean}
351+
*/
352+
this.multiFire = false;
353+
354+
/**
355+
* Internal multiFire test flag.
356+
*
357+
* @type {boolean}
358+
*/
359+
this._hasFired = false;
360+
343361
/**
344362
* If the Weapon is tracking a Sprite, should it also track the Sprites rotation?
345363
* 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) {
367385
*/
368386
this._nextFire = 0;
369387

388+
/**
389+
* Internal firing rate time tracking variable used by multiFire.
390+
*
391+
* @type {number}
392+
* @private
393+
*/
394+
this._tempNextFire = 0;
395+
370396
/**
371397
* Internal firing rotation tracking point.
372398
*
@@ -623,6 +649,25 @@ Phaser.Weapon.prototype.update = function () {
623649

624650
};
625651

652+
/**
653+
* Internal update method, called by the PluginManager.
654+
*
655+
* @method Phaser.Weapon#postRender
656+
* @protected
657+
*/
658+
Phaser.Weapon.prototype.postRender = function () {
659+
660+
if (!this.multiFire || !this._hasFired)
661+
{
662+
return;
663+
}
664+
665+
this._hasFired = false;
666+
667+
this._nextFire = this._tempNextFire;
668+
669+
};
670+
626671
/**
627672
* Sets this Weapon to track the given Sprite, or any Object with a public `world` Point object.
628673
* 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) {
688733

689734
};
690735

736+
/**
737+
* Attempts to fire multiple bullets from the positions defined in the given array.
738+
*
739+
* If you provide a `from` argument, or if there is a tracked Sprite or Pointer, then
740+
* the positions are treated as __offsets__ from the given objects position.
741+
*
742+
* If `from` is undefined, and there is no tracked object, then the bullets are fired
743+
* from the given positions, as they exist in the world.
744+
*
745+
* Calling this method sets `Weapon.multiFire = true`.
746+
*
747+
* If there are not enough bullets available in the pool, and the pool cannot be extended,
748+
* then this method may not fire from all of the given positions.
749+
*
750+
* When the bullets are launched they have their texture and frame updated, as required.
751+
* The velocity of the bullets are calculated based on Weapon properties like `bulletSpeed`.
752+
*
753+
* @method Phaser.Weapon#fireMany
754+
* @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.
755+
* @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.
756+
* @return {array} An array containing all of the fired Phaser.Bullet objects, if a launch was successful, otherwise an empty array.
757+
*/
758+
Phaser.Weapon.prototype.fireMany = function (positions, from) {
759+
760+
this.multiFire = true;
761+
762+
var bullets = [];
763+
764+
var _this = this;
765+
766+
if (from || this.trackedSprite || this.trackedPointer)
767+
{
768+
positions.forEach(function(offset) {
769+
770+
bullets.push(_this.fire(from, null, null, offset.x, offset.y));
771+
772+
});
773+
}
774+
else
775+
{
776+
positions.forEach(function(position) {
777+
778+
bullets.push(_this.fire(position));
779+
780+
});
781+
}
782+
783+
return bullets;
784+
785+
};
786+
787+
/**
788+
* Attempts to fire a single Bullet from a tracked Sprite or Pointer, but applies an offset
789+
* to the position first. This is the same as calling `Weapon.fire` and passing in the offset arguments.
790+
*
791+
* If there are no more bullets available in the pool, and the pool cannot be extended,
792+
* then this method returns `null`. It will also return `null` if not enough time has expired since the last time
793+
* the Weapon was fired, as defined in the `Weapon.fireRate` property.
794+
*
795+
* Otherwise the first available bullet is selected, launched, and returned.
796+
*
797+
* When the bullet is launched it has its texture and frame updated, as required. The velocity of the bullet is
798+
* calculated based on Weapon properties like `bulletSpeed`.
799+
*
800+
* If you wish to fire multiple bullets in a single game update, then set `Weapon.multiFire = true`
801+
* and you can call this method as many times as you like, per loop. See also `Weapon.fireMany`.
802+
*
803+
* @method Phaser.Weapon#fireOffset
804+
* @param {number} [offsetX=0] - The horizontal offset from the position of the tracked Sprite or Pointer, as set with `Weapon.trackSprite`.
805+
* @param {number} [offsetY=0] - The vertical offset from the position of the tracked Sprite or Pointer, as set with `Weapon.trackSprite`.
806+
* @return {Phaser.Bullet} The fired bullet, if a launch was successful, otherwise `null`.
807+
*/
808+
Phaser.Weapon.prototype.fireOffset = function (offsetX, offsetY) {
809+
810+
if (offsetX === undefined) { offsetX = 0; }
811+
if (offsetY === undefined) { offsetY = 0; }
812+
813+
return this.fire(null, null, null, offsetX, offsetY);
814+
815+
};
816+
691817
/**
692818
* Attempts to fire a single Bullet. If there are no more bullets available in the pool, and the pool cannot be extended,
693819
* 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) {
703829
* When the bullet is launched it has its texture and frame updated, as required. The velocity of the bullet is
704830
* calculated based on Weapon properties like `bulletSpeed`.
705831
*
832+
* If you wish to fire multiple bullets in a single game update, then set `Weapon.multiFire = true`
833+
* and you can call `fire` as many times as you like, per loop. Multiple fires in a single update
834+
* only counts once towards the `shots` total, but you will still receive a Signal for each bullet.
835+
*
706836
* @method Phaser.Weapon#fire
707-
* @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.
708-
* @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.
709-
* @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.
837+
* @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.
838+
* @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.
839+
* @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.
840+
* @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.
841+
* @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.
710842
* @return {Phaser.Bullet} The fired bullet, if a launch was successful, otherwise `null`.
711843
*/
712-
Phaser.Weapon.prototype.fire = function (from, x, y) {
844+
Phaser.Weapon.prototype.fire = function (from, x, y, offsetX, offsetY) {
845+
846+
if (x === undefined) { x = null; }
847+
if (y === undefined) { y = null; }
713848

714849
if (this.game.time.now < this._nextFire || (this.fireLimit > 0 && this.shots === this.fireLimit))
715850
{
@@ -784,13 +919,23 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
784919
}
785920
}
786921

922+
if (offsetX !== undefined)
923+
{
924+
this.fireFrom.x += offsetX;
925+
}
926+
927+
if (offsetY !== undefined)
928+
{
929+
this.fireFrom.y += offsetY;
930+
}
931+
787932
var fromX = (this.fireFrom.width > 1) ? this.fireFrom.randomX : this.fireFrom.x;
788933
var fromY = (this.fireFrom.height > 1) ? this.fireFrom.randomY : this.fireFrom.y;
789934

790935
var angle = (this.trackRotation) ? this.trackedSprite.angle : this.fireAngle;
791936

792937
// The position (in world space) to fire the bullet towards, if set
793-
if (x !== undefined && y !== undefined)
938+
if (x !== null && y !== null)
794939
{
795940
angle = this.game.math.radToDeg(Math.atan2(y - fromY, x - fromX));
796941
}
@@ -895,6 +1040,8 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
8951040
bullet.body.velocity.set(moveX, moveY);
8961041
bullet.body.gravity.set(this.bulletGravity.x, this.bulletGravity.y);
8971042

1043+
var next = 0;
1044+
8981045
if (this.bulletSpeedVariance !== 0)
8991046
{
9001047
var rate = this.fireRate;
@@ -906,14 +1053,29 @@ Phaser.Weapon.prototype.fire = function (from, x, y) {
9061053
rate = 0;
9071054
}
9081055

909-
this._nextFire = this.game.time.now + rate;
1056+
next = this.game.time.now + rate;
9101057
}
9111058
else
9121059
{
913-
this._nextFire = this.game.time.now + this.fireRate;
1060+
next = this.game.time.now + this.fireRate;
9141061
}
9151062

916-
this.shots++;
1063+
if (this.multiFire)
1064+
{
1065+
if (!this._hasFired)
1066+
{
1067+
// We only add 1 to the 'shots' count for multiFire shots
1068+
this._hasFired = true;
1069+
this._tempNextFire = next;
1070+
this.shots++;
1071+
}
1072+
}
1073+
else
1074+
{
1075+
this._nextFire = next;
1076+
1077+
this.shots++;
1078+
}
9171079

9181080
this.onFire.dispatch(bullet, this, speed);
9191081

typescript/phaser.d.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// <reference path="pixi.d.ts" />
22
/// <reference path="p2.d.ts" />
33

4-
// Type definitions for Phaser 2.6.2 - 26th August 2016
4+
// Type definitions for Phaser 3.0.0 - 7th September 2016
55
// Project: https://github.com/photonstorm/phaser
66

77
declare module "phaser" {
@@ -5636,6 +5636,7 @@ declare module Phaser {
56365636
fireLimit: number;
56375637
fireRate: number;
56385638
fireRateVariance: number;
5639+
multiFire: boolean;
56395640
onFire: Phaser.Signal;
56405641
onFireLimit: Phaser.Signal;
56415642
onKill: Phaser.Signal;
@@ -5651,10 +5652,12 @@ declare module Phaser {
56515652
createBullets(quantity?: number, key?: any, frame?: any, group?: Phaser.Group): Phaser.Weapon;
56525653
debug(x?: number, y?: number, debugBodies?: boolean): void;
56535654
destroy(): void;
5654-
fire(from?: any, x?: number, y?: number): Phaser.Bullet;
5655+
fire(from?: any, x?: number, y?: number, offsetX?: number, offsetY?: number): Phaser.Bullet;
56555656
fireAtPointer(pointer: Phaser.Pointer): Phaser.Bullet;
56565657
fireAtSprite(sprite: Phaser.Sprite): Phaser.Bullet;
56575658
fireAtXY(x: number, y: number): Phaser.Bullet;
5659+
fireMany(positions: any[], from?: any): Phaser.Bullet[];
5660+
fireOffset(offsetX?: number, offsetY?: number): Phaser.Bullet;
56585661
forEach(callback: any, callbackContext: any): Phaser.Weapon;
56595662
killAll(): Phaser.Weapon;
56605663
pauseAll(): Phaser.Weapon;

0 commit comments

Comments
 (0)