phaser/src/gameobjects/components/Transform.js
2020-03-27 21:18:49 -07:00

533 lines
14 KiB
JavaScript

/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var MATH_CONST = require('../../math/const');
var TransformMatrix = require('./TransformMatrix');
var WrapAngle = require('../../math/angle/Wrap');
var WrapAngleDegrees = require('../../math/angle/WrapDegrees');
// global bitmask flag for GameObject.renderMask (used by Scale)
var _FLAG = 4; // 0100
/**
* Provides methods used for getting and setting the position, scale and rotation of a Game Object.
*
* @namespace Phaser.GameObjects.Components.Transform
* @since 3.0.0
*/
var Transform = {
/**
* Private internal value. Holds the horizontal scale value.
*
* @name Phaser.GameObjects.Components.Transform#_scaleX
* @type {number}
* @private
* @default 1
* @since 3.0.0
*/
_scaleX: 1,
/**
* Private internal value. Holds the vertical scale value.
*
* @name Phaser.GameObjects.Components.Transform#_scaleY
* @type {number}
* @private
* @default 1
* @since 3.0.0
*/
_scaleY: 1,
/**
* Private internal value. Holds the rotation value in radians.
*
* @name Phaser.GameObjects.Components.Transform#_rotation
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
_rotation: 0,
/**
* The x position of this Game Object.
*
* @name Phaser.GameObjects.Components.Transform#x
* @type {number}
* @default 0
* @since 3.0.0
*/
x: 0,
/**
* The y position of this Game Object.
*
* @name Phaser.GameObjects.Components.Transform#y
* @type {number}
* @default 0
* @since 3.0.0
*/
y: 0,
/**
* The z position of this Game Object.
*
* Note: The z position does not control the rendering order of 2D Game Objects. Use
* {@link Phaser.GameObjects.Components.Depth#depth} instead.
*
* @name Phaser.GameObjects.Components.Transform#z
* @type {number}
* @default 0
* @since 3.0.0
*/
z: 0,
/**
* The w position of this Game Object.
*
* @name Phaser.GameObjects.Components.Transform#w
* @type {number}
* @default 0
* @since 3.0.0
*/
w: 0,
/**
* This is a special setter that allows you to set both the horizontal and vertical scale of this Game Object
* to the same value, at the same time. When reading this value the result returned is `(scaleX + scaleY) / 2`.
*
* Use of this property implies you wish the horizontal and vertical scales to be equal to each other. If this
* isn't the case, use the `scaleX` or `scaleY` properties instead.
*
* @name Phaser.GameObjects.Components.Transform#scale
* @type {number}
* @default 1
* @since 3.18.0
*/
scale: {
get: function ()
{
return (this._scaleX + this._scaleY) / 2;
},
set: function (value)
{
this._scaleX = value;
this._scaleY = value;
if (value === 0)
{
this.renderFlags &= ~_FLAG;
}
else
{
this.renderFlags |= _FLAG;
}
}
},
/**
* The horizontal scale of this Game Object.
*
* @name Phaser.GameObjects.Components.Transform#scaleX
* @type {number}
* @default 1
* @since 3.0.0
*/
scaleX: {
get: function ()
{
return this._scaleX;
},
set: function (value)
{
this._scaleX = value;
if (value === 0)
{
this.renderFlags &= ~_FLAG;
}
else
{
this.renderFlags |= _FLAG;
}
}
},
/**
* The vertical scale of this Game Object.
*
* @name Phaser.GameObjects.Components.Transform#scaleY
* @type {number}
* @default 1
* @since 3.0.0
*/
scaleY: {
get: function ()
{
return this._scaleY;
},
set: function (value)
{
this._scaleY = value;
if (value === 0)
{
this.renderFlags &= ~_FLAG;
}
else
{
this.renderFlags |= _FLAG;
}
}
},
/**
* The angle of this Game Object as expressed in degrees.
*
* Phaser uses a right-hand clockwise rotation system, where 0 is right, 90 is down, 180/-180 is left
* and -90 is up.
*
* If you prefer to work in radians, see the `rotation` property instead.
*
* @name Phaser.GameObjects.Components.Transform#angle
* @type {integer}
* @default 0
* @since 3.0.0
*/
angle: {
get: function ()
{
return WrapAngleDegrees(this._rotation * MATH_CONST.RAD_TO_DEG);
},
set: function (value)
{
// value is in degrees
this.rotation = WrapAngleDegrees(value) * MATH_CONST.DEG_TO_RAD;
}
},
/**
* The angle of this Game Object in radians.
*
* Phaser uses a right-hand clockwise rotation system, where 0 is right, PI/2 is down, +-PI is left
* and -PI/2 is up.
*
* If you prefer to work in degrees, see the `angle` property instead.
*
* @name Phaser.GameObjects.Components.Transform#rotation
* @type {number}
* @default 1
* @since 3.0.0
*/
rotation: {
get: function ()
{
return this._rotation;
},
set: function (value)
{
// value is in radians
this._rotation = WrapAngle(value);
}
},
/**
* Sets the position of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setPosition
* @since 3.0.0
*
* @param {number} [x=0] - The x position of this Game Object.
* @param {number} [y=x] - The y position of this Game Object. If not set it will use the `x` value.
* @param {number} [z=0] - The z position of this Game Object.
* @param {number} [w=0] - The w position of this Game Object.
*
* @return {this} This Game Object instance.
*/
setPosition: function (x, y, z, w)
{
if (x === undefined) { x = 0; }
if (y === undefined) { y = x; }
if (z === undefined) { z = 0; }
if (w === undefined) { w = 0; }
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
},
/**
* Sets the position of this Game Object to be a random position within the confines of
* the given area.
*
* If no area is specified a random position between 0 x 0 and the game width x height is used instead.
*
* The position does not factor in the size of this Game Object, meaning that only the origin is
* guaranteed to be within the area.
*
* @method Phaser.GameObjects.Components.Transform#setRandomPosition
* @since 3.8.0
*
* @param {number} [x=0] - The x position of the top-left of the random area.
* @param {number} [y=0] - The y position of the top-left of the random area.
* @param {number} [width] - The width of the random area.
* @param {number} [height] - The height of the random area.
*
* @return {this} This Game Object instance.
*/
setRandomPosition: function (x, y, width, height)
{
if (x === undefined) { x = 0; }
if (y === undefined) { y = 0; }
if (width === undefined) { width = this.scene.sys.scale.width; }
if (height === undefined) { height = this.scene.sys.scale.height; }
this.x = x + (Math.random() * width);
this.y = y + (Math.random() * height);
return this;
},
/**
* Sets the rotation of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setRotation
* @since 3.0.0
*
* @param {number} [radians=0] - The rotation of this Game Object, in radians.
*
* @return {this} This Game Object instance.
*/
setRotation: function (radians)
{
if (radians === undefined) { radians = 0; }
this.rotation = radians;
return this;
},
/**
* Sets the angle of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setAngle
* @since 3.0.0
*
* @param {number} [degrees=0] - The rotation of this Game Object, in degrees.
*
* @return {this} This Game Object instance.
*/
setAngle: function (degrees)
{
if (degrees === undefined) { degrees = 0; }
this.angle = degrees;
return this;
},
/**
* Sets the scale of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setScale
* @since 3.0.0
*
* @param {number} x - The horizontal scale of this Game Object.
* @param {number} [y=x] - The vertical scale of this Game Object. If not set it will use the `x` value.
*
* @return {this} This Game Object instance.
*/
setScale: function (x, y)
{
if (x === undefined) { x = 1; }
if (y === undefined) { y = x; }
this.scaleX = x;
this.scaleY = y;
return this;
},
/**
* Sets the x position of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setX
* @since 3.0.0
*
* @param {number} [value=0] - The x position of this Game Object.
*
* @return {this} This Game Object instance.
*/
setX: function (value)
{
if (value === undefined) { value = 0; }
this.x = value;
return this;
},
/**
* Sets the y position of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setY
* @since 3.0.0
*
* @param {number} [value=0] - The y position of this Game Object.
*
* @return {this} This Game Object instance.
*/
setY: function (value)
{
if (value === undefined) { value = 0; }
this.y = value;
return this;
},
/**
* Sets the z position of this Game Object.
*
* Note: The z position does not control the rendering order of 2D Game Objects. Use
* {@link Phaser.GameObjects.Components.Depth#setDepth} instead.
*
* @method Phaser.GameObjects.Components.Transform#setZ
* @since 3.0.0
*
* @param {number} [value=0] - The z position of this Game Object.
*
* @return {this} This Game Object instance.
*/
setZ: function (value)
{
if (value === undefined) { value = 0; }
this.z = value;
return this;
},
/**
* Sets the w position of this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#setW
* @since 3.0.0
*
* @param {number} [value=0] - The w position of this Game Object.
*
* @return {this} This Game Object instance.
*/
setW: function (value)
{
if (value === undefined) { value = 0; }
this.w = value;
return this;
},
/**
* Gets the local transform matrix for this Game Object.
*
* @method Phaser.GameObjects.Components.Transform#getLocalTransformMatrix
* @since 3.4.0
*
* @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object.
*
* @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix.
*/
getLocalTransformMatrix: function (tempMatrix)
{
if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); }
return tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY);
},
/**
* Gets the world transform matrix for this Game Object, factoring in any parent Containers.
*
* @method Phaser.GameObjects.Components.Transform#getWorldTransformMatrix
* @since 3.4.0
*
* @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - A temporary matrix to hold parent values during the calculations.
*
* @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix.
*/
getWorldTransformMatrix: function (tempMatrix, parentMatrix)
{
if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); }
if (parentMatrix === undefined) { parentMatrix = new TransformMatrix(); }
var parent = this.parentContainer;
if (!parent)
{
return this.getLocalTransformMatrix(tempMatrix);
}
tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY);
while (parent)
{
parentMatrix.applyITRS(parent.x, parent.y, parent._rotation, parent._scaleX, parent._scaleY);
parentMatrix.multiply(tempMatrix, tempMatrix);
parent = parent.parentContainer;
}
return tempMatrix;
},
/**
* Gets the sum total rotation of all of this Game Objects parent Containers.
*
* The returned value is in radians and will be zero if this Game Object has no parent container.
*
* @method Phaser.GameObjects.Components.Transform#getParentRotation
* @since 3.18.0
*
* @return {number} The sum total rotation, in radians, of all parent containers of this Game Object.
*/
getParentRotation: function ()
{
var rotation = 0;
var parent = this.parentContainer;
while (parent)
{
rotation += parent.rotation;
parent = parent.parentContainer;
}
return rotation;
}
};
module.exports = Transform;