mirror of
https://github.com/photonstorm/phaser
synced 2024-12-23 19:43:28 +00:00
Added RotateTo Effect to Camera
This commit is contained in:
parent
06688eedd8
commit
ada7fbc990
3 changed files with 454 additions and 0 deletions
|
@ -117,6 +117,16 @@ var Camera = new Class({
|
||||||
*/
|
*/
|
||||||
this.panEffect = new Effects.Pan(this);
|
this.panEffect = new Effects.Pan(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Camera Rotate To effect handler.
|
||||||
|
* To rotate this camera see the `Camera.rotateTo` method.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Camera#rotateToEffect
|
||||||
|
* @type {Phaser.Cameras.Scene2D.Effects.RotateTo}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.rotateToEffect = new Effects.RotateTo(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Camera Zoom effect handler.
|
* The Camera Zoom effect handler.
|
||||||
* To zoom this camera see the `Camera.zoom` method.
|
* To zoom this camera see the `Camera.zoom` method.
|
||||||
|
@ -635,6 +645,30 @@ var Camera = new Class({
|
||||||
return this.panEffect.start(x, y, duration, ease, force, callback, context);
|
return this.panEffect.start(x, y, duration, ease, force, callback, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This effect will rotate the Camera so that the viewport finishes at the given angle in radians,
|
||||||
|
* over the duration and with the ease specified.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Camera#rotateTo
|
||||||
|
* @since 3.16.0
|
||||||
|
*
|
||||||
|
* @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise
|
||||||
|
* @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise.
|
||||||
|
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
|
||||||
|
* @param {(string|function)} [ease='Linear'] - The ease to use for the rotation. Can be any of the Phaser Easing constants or a custom function.
|
||||||
|
* @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running.
|
||||||
|
* @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
|
||||||
|
* It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is,
|
||||||
|
* the current camera rotation angle in radians.
|
||||||
|
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Cameras.Scene2D.Camera} This Camera instance.
|
||||||
|
*/
|
||||||
|
rotateTo: function (radians, shortestPath, duration, ease, force, callback, context)
|
||||||
|
{
|
||||||
|
return this.rotateToEffect.start(radians, shortestPath, duration, ease, force, callback, context);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This effect will zoom the Camera to the given scale, over the duration and with the ease specified.
|
* This effect will zoom the Camera to the given scale, over the duration and with the ease specified.
|
||||||
*
|
*
|
||||||
|
@ -902,6 +936,7 @@ var Camera = new Class({
|
||||||
*/
|
*/
|
||||||
resetFX: function ()
|
resetFX: function ()
|
||||||
{
|
{
|
||||||
|
this.rotateToEffect.reset();
|
||||||
this.panEffect.reset();
|
this.panEffect.reset();
|
||||||
this.shakeEffect.reset();
|
this.shakeEffect.reset();
|
||||||
this.flashEffect.reset();
|
this.flashEffect.reset();
|
||||||
|
@ -924,6 +959,7 @@ var Camera = new Class({
|
||||||
{
|
{
|
||||||
if (this.visible)
|
if (this.visible)
|
||||||
{
|
{
|
||||||
|
this.rotateToEffect.update(time, delta);
|
||||||
this.panEffect.update(time, delta);
|
this.panEffect.update(time, delta);
|
||||||
this.zoomEffect.update(time, delta);
|
this.zoomEffect.update(time, delta);
|
||||||
this.shakeEffect.update(time, delta);
|
this.shakeEffect.update(time, delta);
|
||||||
|
|
417
src/cameras/2d/effects/RotateTo.js
Normal file
417
src/cameras/2d/effects/RotateTo.js
Normal file
|
@ -0,0 +1,417 @@
|
||||||
|
/**
|
||||||
|
* @author Jason Nicholls <nicholls.jason@gmail.com>
|
||||||
|
* @copyright 2018 Photon Storm Ltd.
|
||||||
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Clamp = require('../../../math/Clamp');
|
||||||
|
var Class = require('../../../utils/Class');
|
||||||
|
var EaseMap = require('../../../math/easing/EaseMap');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* A Camera Rotate effect.
|
||||||
|
*
|
||||||
|
* This effect will rotate the Camera so that the its viewport finishes at the given angle in radians,
|
||||||
|
* over the duration and with the ease specified.
|
||||||
|
*
|
||||||
|
* Camera rotation always takes place based on the Camera viewport. By default, rotation happens
|
||||||
|
* in the center of the viewport. You can adjust this with the `originX` and `originY` properties.
|
||||||
|
*
|
||||||
|
* Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not
|
||||||
|
* rotate the Camera viewport itself, which always remains an axis-aligned rectangle.
|
||||||
|
*
|
||||||
|
* Only the camera is rotates. None of the objects it is displaying are impacted, i.e. their positions do
|
||||||
|
* not change.
|
||||||
|
*
|
||||||
|
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
|
||||||
|
* which is invoked each frame for the duration of the effect if required.
|
||||||
|
*
|
||||||
|
* @class RotateTo
|
||||||
|
* @memberof Phaser.Cameras.Scene2D.Effects
|
||||||
|
* @constructor
|
||||||
|
* @since 3.16.0
|
||||||
|
*
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
|
||||||
|
*/
|
||||||
|
var RotateTo = new Class({
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function RotateTo (camera)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The Camera this effect belongs to.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#camera
|
||||||
|
* @type {Phaser.Cameras.Scene2D.Camera}
|
||||||
|
* @readonly
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.camera = camera;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this effect actively running?
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#isRunning
|
||||||
|
* @type {boolean}
|
||||||
|
* @readonly
|
||||||
|
* @default false
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.isRunning = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration of the effect, in milliseconds.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#duration
|
||||||
|
* @type {integer}
|
||||||
|
* @readonly
|
||||||
|
* @default 0
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.duration = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The starting angle to rotate the camera from.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#source
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.source = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constantly updated value based on the force.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#current
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.current = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The destination angle in radians to rotate the camera to.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#destination
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.destination = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ease function to use during the Rotate.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#ease
|
||||||
|
* @type {function}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.ease;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#progress
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.progress = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Effect elapsed timer.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_elapsed
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this._elapsed = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @callback CameraRotateCallback
|
||||||
|
*
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera on which the effect is running.
|
||||||
|
* @param {number} progress - The progress of the effect. A value between 0 and 1.
|
||||||
|
* @param {number} angle - The Camera's new angle in radians.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is invoked every frame for the duration of the effect.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdate
|
||||||
|
* @type {?CameraRotateCallback}
|
||||||
|
* @private
|
||||||
|
* @default null
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this._onUpdate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Complete callback scope.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdateScope
|
||||||
|
* @type {any}
|
||||||
|
* @private
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this._onUpdateScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The direction of the rotation.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#clockwise
|
||||||
|
* @type {boolean}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.clockwise = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shortest direction to the target rotation.
|
||||||
|
*
|
||||||
|
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#shortestPath
|
||||||
|
* @type {boolean}
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
this.shortestPath = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is fired when the Rotate effect begins to run on a camera.
|
||||||
|
*
|
||||||
|
* @event CameraRotateStartEvent
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
|
||||||
|
* @param {integer} duration - The duration of the effect.
|
||||||
|
* @param {number} angle - The destination angle in radians.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is fired when the Rotate effect completes.
|
||||||
|
*
|
||||||
|
* @event CameraRotateCompleteEvent
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This effect will scroll the Camera so that the center of its viewport finishes at the given angle,
|
||||||
|
* over the duration and with the ease specified.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#start
|
||||||
|
* @fires CameraRotateStartEvent
|
||||||
|
* @fires CameraRotateCompleteEvent
|
||||||
|
* @since 3.16.0
|
||||||
|
*
|
||||||
|
* @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise
|
||||||
|
* @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise.
|
||||||
|
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
|
||||||
|
* @param {(string|function)} [ease='Linear'] - The ease to use for the Rotate. Can be any of the Phaser Easing constants or a custom function.
|
||||||
|
* @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running.
|
||||||
|
* @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
|
||||||
|
* It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is,
|
||||||
|
* the current camera scroll x coordinate and the current camera scroll y coordinate.
|
||||||
|
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
|
||||||
|
*/
|
||||||
|
start: function (radians, shortestPath, duration, ease, force, callback, context)
|
||||||
|
{
|
||||||
|
if (duration === undefined) { duration = 1000; }
|
||||||
|
if (ease === undefined) { ease = EaseMap.Linear; }
|
||||||
|
if (force === undefined) { force = false; }
|
||||||
|
if (callback === undefined) { callback = null; }
|
||||||
|
if (context === undefined) { context = this.camera.scene; }
|
||||||
|
if (shortestPath === undefined) {shortestPath = false;}
|
||||||
|
this.shortestPath = shortestPath;
|
||||||
|
|
||||||
|
var tmpDestination = radians;
|
||||||
|
if (radians < 0) {
|
||||||
|
tmpDestination = -1 * radians;
|
||||||
|
this.clockwise = false;
|
||||||
|
} else {
|
||||||
|
this.clockwise = true;
|
||||||
|
}
|
||||||
|
var maxRad = (360 * Math.PI) / 180;
|
||||||
|
tmpDestination = tmpDestination - (Math.floor(tmpDestination / maxRad) * maxRad);
|
||||||
|
|
||||||
|
var cam = this.camera;
|
||||||
|
|
||||||
|
if (!force && this.isRunning)
|
||||||
|
{
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isRunning = true;
|
||||||
|
this.duration = duration;
|
||||||
|
this.progress = 0;
|
||||||
|
|
||||||
|
// Starting from
|
||||||
|
this.source = cam.rotation;
|
||||||
|
|
||||||
|
// Destination
|
||||||
|
this.destination = tmpDestination;
|
||||||
|
|
||||||
|
// Using this ease
|
||||||
|
if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease))
|
||||||
|
{
|
||||||
|
this.ease = EaseMap[ease];
|
||||||
|
}
|
||||||
|
else if (typeof ease === 'function')
|
||||||
|
{
|
||||||
|
this.ease = ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._elapsed = 0;
|
||||||
|
|
||||||
|
this._onUpdate = callback;
|
||||||
|
this._onUpdateScope = context;
|
||||||
|
|
||||||
|
|
||||||
|
if (this.shortestPath === true) {
|
||||||
|
// The shotest path is true so calculate the quickest direction
|
||||||
|
var cwDist = 0;
|
||||||
|
var acwDist = 0;
|
||||||
|
if (this.clockwise === false) {
|
||||||
|
target = this.current;
|
||||||
|
current = this.destination;
|
||||||
|
}
|
||||||
|
if (this.destination > this.source) {
|
||||||
|
cwDist = Math.abs(this.destination - this.source);
|
||||||
|
} else {
|
||||||
|
cwDist = (Math.abs(this.destination + maxRad) - this.source);
|
||||||
|
}
|
||||||
|
if (this.source > this.destination) {
|
||||||
|
acwDist = Math.abs(this.source - this.destination);
|
||||||
|
} else {
|
||||||
|
acwDist = (Math.abs(this.source + maxRad) - this.destination);
|
||||||
|
}
|
||||||
|
if (cwDist < acwDist) {
|
||||||
|
this.clockwise = true;
|
||||||
|
} else if (cwDist > acwDist) {
|
||||||
|
this.clockwise = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.camera.emit('camerarotatestart', this.camera, this, duration, tmpDestination);
|
||||||
|
|
||||||
|
return cam;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main update loop for this effect. Called automatically by the Camera.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#update
|
||||||
|
* @since 3.16.0
|
||||||
|
*
|
||||||
|
* @param {integer} time - The current timestamp as generated by the Request Animation Frame or SetTimeout.
|
||||||
|
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
|
||||||
|
*/
|
||||||
|
update: function (time, delta)
|
||||||
|
{
|
||||||
|
if (!this.isRunning)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._elapsed += delta;
|
||||||
|
|
||||||
|
var progress = Clamp(this._elapsed / this.duration, 0, 1);
|
||||||
|
|
||||||
|
this.progress = progress;
|
||||||
|
|
||||||
|
var cam = this.camera;
|
||||||
|
|
||||||
|
if (this._elapsed < this.duration)
|
||||||
|
{
|
||||||
|
var v = this.ease(progress);
|
||||||
|
|
||||||
|
this.current = cam.rotation;
|
||||||
|
var distance = 0;
|
||||||
|
var maxRad = (360 * Math.PI) / 180;
|
||||||
|
var target = this.destination;
|
||||||
|
var current = this.current;
|
||||||
|
if (this.clockwise === false) {
|
||||||
|
target = this.current;
|
||||||
|
current = this.destination;
|
||||||
|
}
|
||||||
|
if (target >= current) {
|
||||||
|
distance = Math.abs(target - current);
|
||||||
|
} else {
|
||||||
|
distance = (Math.abs(target + maxRad) - current);
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = 0;
|
||||||
|
if (this.clockwise) {
|
||||||
|
r = (cam.rotation + (distance * v));
|
||||||
|
} else {
|
||||||
|
r = (cam.rotation - (distance * v));
|
||||||
|
}
|
||||||
|
cam.rotation = r;
|
||||||
|
|
||||||
|
if (this._onUpdate)
|
||||||
|
{
|
||||||
|
this._onUpdate.call(this._onUpdateScope, cam, progress, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cam.rotation = this.destination;
|
||||||
|
|
||||||
|
if (this._onUpdate)
|
||||||
|
{
|
||||||
|
this._onUpdate.call(this._onUpdateScope, cam, progress, this.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.effectComplete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called internally when the effect completes.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#effectComplete
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
effectComplete: function ()
|
||||||
|
{
|
||||||
|
this._onUpdate = null;
|
||||||
|
this._onUpdateScope = null;
|
||||||
|
|
||||||
|
this.isRunning = false;
|
||||||
|
|
||||||
|
this.camera.emit('camerarotatecomplete', this.camera, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets this camera effect.
|
||||||
|
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#reset
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
reset: function ()
|
||||||
|
{
|
||||||
|
this.isRunning = false;
|
||||||
|
|
||||||
|
this._onUpdate = null;
|
||||||
|
this._onUpdateScope = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys this effect, releasing it from the Camera.
|
||||||
|
*
|
||||||
|
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#destroy
|
||||||
|
* @since 3.16.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.reset();
|
||||||
|
|
||||||
|
this.camera = null;
|
||||||
|
this.source = null;
|
||||||
|
this.destination = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = RotateTo;
|
|
@ -14,6 +14,7 @@ module.exports = {
|
||||||
Flash: require('./Flash'),
|
Flash: require('./Flash'),
|
||||||
Pan: require('./Pan'),
|
Pan: require('./Pan'),
|
||||||
Shake: require('./Shake'),
|
Shake: require('./Shake'),
|
||||||
|
RotateTo: require('./RotateTo'),
|
||||||
Zoom: require('./Zoom')
|
Zoom: require('./Zoom')
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue