2018-09-05 15:20:25 +00:00
|
|
|
/**
|
|
|
|
* @author Richard Davey <rich@photonstorm.com>
|
2019-01-15 16:20:22 +00:00
|
|
|
* @copyright 2019 Photon Storm Ltd.
|
2019-05-10 15:15:04 +00:00
|
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
2018-09-05 15:20:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
var ArcRender = require('./ArcRender');
|
2018-09-06 10:26:50 +00:00
|
|
|
var Class = require('../../../utils/Class');
|
|
|
|
var DegToRad = require('../../../math/DegToRad');
|
|
|
|
var Earcut = require('../../../geom/polygon/Earcut');
|
|
|
|
var GeomCircle = require('../../../geom/circle/Circle');
|
|
|
|
var MATH_CONST = require('../../../math/const');
|
2018-09-07 11:09:57 +00:00
|
|
|
var Shape = require('../Shape');
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @classdesc
|
2018-09-15 09:31:10 +00:00
|
|
|
* The Arc Shape is a Game Object that can be added to a Scene, Group or Container. You can
|
|
|
|
* treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling
|
|
|
|
* it for input or physics. It provides a quick and easy way for you to render this shape in your
|
|
|
|
* game without using a texture, while still taking advantage of being fully batched in WebGL.
|
|
|
|
*
|
|
|
|
* This shape supports both fill and stroke colors.
|
|
|
|
*
|
|
|
|
* When it renders it displays an arc shape. You can control the start and end angles of the arc,
|
|
|
|
* as well as if the angles are winding clockwise or anti-clockwise. With the default settings
|
|
|
|
* it renders as a complete circle. By changing the angles you can create other arc shapes,
|
|
|
|
* such as half-circles.
|
|
|
|
*
|
|
|
|
* Arcs also have an `iterations` property and corresponding `setIterations` method. This allows
|
|
|
|
* you to control how smooth the shape renders in WebGL, by controlling the number of iterations
|
|
|
|
* that take place during construction.
|
2018-09-05 15:20:25 +00:00
|
|
|
*
|
|
|
|
* @class Arc
|
|
|
|
* @extends Phaser.GameObjects.Shape
|
2018-10-10 09:49:13 +00:00
|
|
|
* @memberof Phaser.GameObjects
|
2018-09-05 15:20:25 +00:00
|
|
|
* @constructor
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
|
2018-09-10 21:47:39 +00:00
|
|
|
* @param {number} [x=0] - The horizontal position of this Game Object in the world.
|
|
|
|
* @param {number} [y=0] - The vertical position of this Game Object in the world.
|
|
|
|
* @param {number} [radius=128] - The radius of the arc.
|
|
|
|
* @param {integer} [startAngle=0] - The start angle of the arc, in degrees.
|
|
|
|
* @param {integer} [endAngle=360] - The end angle of the arc, in degrees.
|
|
|
|
* @param {boolean} [anticlockwise=false] - The winding order of the start and end angles.
|
|
|
|
* @param {number} [fillColor] - The color the arc will be filled with, i.e. 0xff0000 for red.
|
|
|
|
* @param {number} [fillAlpha] - The alpha the arc will be filled with. You can also set the alpha of the overall Shape using its `alpha` property.
|
2018-09-05 15:20:25 +00:00
|
|
|
*/
|
|
|
|
var Arc = new Class({
|
|
|
|
|
|
|
|
Extends: Shape,
|
|
|
|
|
|
|
|
Mixins: [
|
|
|
|
ArcRender
|
|
|
|
],
|
|
|
|
|
|
|
|
initialize:
|
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
function Arc (scene, x, y, radius, startAngle, endAngle, anticlockwise, fillColor, fillAlpha)
|
2018-09-05 15:20:25 +00:00
|
|
|
{
|
2018-09-06 14:49:42 +00:00
|
|
|
if (x === undefined) { x = 0; }
|
|
|
|
if (y === undefined) { y = 0; }
|
|
|
|
if (radius === undefined) { radius = 128; }
|
2018-09-05 15:20:25 +00:00
|
|
|
if (startAngle === undefined) { startAngle = 0; }
|
|
|
|
if (endAngle === undefined) { endAngle = 360; }
|
|
|
|
if (anticlockwise === undefined) { anticlockwise = false; }
|
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
Shape.call(this, scene, 'Arc', new GeomCircle(0, 0, radius));
|
2018-09-05 15:20:25 +00:00
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Private internal value. Holds the start angle in degrees.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#_startAngle
|
|
|
|
* @type {integer}
|
|
|
|
* @private
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
this._startAngle = startAngle;
|
2018-09-10 21:47:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private internal value. Holds the end angle in degrees.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#_endAngle
|
|
|
|
* @type {integer}
|
|
|
|
* @private
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
this._endAngle = endAngle;
|
2018-09-10 21:47:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private internal value. Holds the winding order of the start and end angles.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#_anticlockwise
|
|
|
|
* @type {boolean}
|
|
|
|
* @private
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
this._anticlockwise = anticlockwise;
|
2018-09-10 21:47:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private internal value. Holds the number of iterations used when drawing the arc.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#_iterations
|
|
|
|
* @type {number}
|
|
|
|
* @default 0.01
|
|
|
|
* @private
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
this._iterations = 0.01;
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
this.setPosition(x, y);
|
2018-09-12 11:37:18 +00:00
|
|
|
this.setSize(this.geom.radius, this.geom.radius);
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
if (fillColor !== undefined)
|
|
|
|
{
|
|
|
|
this.setFillStyle(fillColor, fillAlpha);
|
|
|
|
}
|
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
this.updateDisplayOrigin();
|
2018-09-05 15:20:25 +00:00
|
|
|
this.updateData();
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* The number of iterations used when drawing the arc.
|
|
|
|
* Increase this value for smoother arcs, at the cost of more polygons being rendered.
|
|
|
|
* Modify this value by small amounts, such as 0.01.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#iterations
|
|
|
|
* @type {number}
|
|
|
|
* @default 0.01
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
iterations: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
return this._iterations;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
|
|
|
this._iterations = value;
|
|
|
|
|
|
|
|
this.updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* The radius of the arc.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#radius
|
|
|
|
* @type {number}
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
radius: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
2018-09-12 11:37:18 +00:00
|
|
|
return this.geom.radius;
|
2018-09-07 11:09:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
2018-09-12 11:37:18 +00:00
|
|
|
this.geom.radius = value;
|
2018-09-07 11:09:57 +00:00
|
|
|
|
2019-06-05 22:02:59 +00:00
|
|
|
this.setSize(value, value);
|
|
|
|
this.updateDisplayOrigin();
|
2018-09-07 11:09:57 +00:00
|
|
|
this.updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* The start angle of the arc, in degrees.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#startAngle
|
|
|
|
* @type {integer}
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
startAngle: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
return this._startAngle;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
|
|
|
this._startAngle = value;
|
|
|
|
|
|
|
|
this.updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* The end angle of the arc, in degrees.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#endAngle
|
|
|
|
* @type {integer}
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
endAngle: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
return this._endAngle;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
|
|
|
this._endAngle = value;
|
|
|
|
|
|
|
|
this.updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* The winding order of the start and end angles.
|
|
|
|
*
|
|
|
|
* @name Phaser.GameObjects.Arc#anticlockwise
|
|
|
|
* @type {boolean}
|
|
|
|
* @since 3.13.0
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
anticlockwise: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
return this._anticlockwise;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
|
|
|
this._anticlockwise = value;
|
|
|
|
|
|
|
|
this.updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Sets the radius of the arc.
|
|
|
|
* This call can be chained.
|
|
|
|
*
|
|
|
|
* @method Phaser.GameObjects.Arc#setRadius
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @param {number} value - The value to set the radius to.
|
|
|
|
*
|
|
|
|
* @return {this} This Game Object instance.
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
setRadius: function (value)
|
|
|
|
{
|
|
|
|
this.radius = value;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Sets the number of iterations used when drawing the arc.
|
|
|
|
* Increase this value for smoother arcs, at the cost of more polygons being rendered.
|
|
|
|
* Modify this value by small amounts, such as 0.01.
|
|
|
|
* This call can be chained.
|
|
|
|
*
|
|
|
|
* @method Phaser.GameObjects.Arc#setIterations
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @param {number} value - The value to set the iterations to.
|
|
|
|
*
|
|
|
|
* @return {this} This Game Object instance.
|
|
|
|
*/
|
2018-09-07 11:09:57 +00:00
|
|
|
setIterations: function (value)
|
2018-09-05 15:20:25 +00:00
|
|
|
{
|
|
|
|
if (value === undefined) { value = 0.01; }
|
|
|
|
|
|
|
|
this.iterations = value;
|
|
|
|
|
2018-09-07 11:09:57 +00:00
|
|
|
return this;
|
2018-09-05 15:20:25 +00:00
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Sets the starting angle of the arc, in degrees.
|
|
|
|
* This call can be chained.
|
|
|
|
*
|
|
|
|
* @method Phaser.GameObjects.Arc#setStartAngle
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @param {integer} value - The value to set the starting angle to.
|
|
|
|
*
|
|
|
|
* @return {this} This Game Object instance.
|
|
|
|
*/
|
2018-09-05 15:20:25 +00:00
|
|
|
setStartAngle: function (angle, anticlockwise)
|
|
|
|
{
|
2018-09-07 11:09:57 +00:00
|
|
|
this._startAngle = angle;
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
if (anticlockwise !== undefined)
|
|
|
|
{
|
2018-09-07 11:09:57 +00:00
|
|
|
this._anticlockwise = anticlockwise;
|
2018-09-05 15:20:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return this.updateData();
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Sets the ending angle of the arc, in degrees.
|
|
|
|
* This call can be chained.
|
|
|
|
*
|
|
|
|
* @method Phaser.GameObjects.Arc#setEndAngle
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @param {integer} value - The value to set the ending angle to.
|
|
|
|
*
|
|
|
|
* @return {this} This Game Object instance.
|
|
|
|
*/
|
2018-09-05 15:20:25 +00:00
|
|
|
setEndAngle: function (angle, anticlockwise)
|
|
|
|
{
|
2018-09-07 11:09:57 +00:00
|
|
|
this._endAngle = angle;
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
if (anticlockwise !== undefined)
|
|
|
|
{
|
2018-09-07 11:09:57 +00:00
|
|
|
this._anticlockwise = anticlockwise;
|
2018-09-05 15:20:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return this.updateData();
|
|
|
|
},
|
|
|
|
|
2018-09-10 21:47:39 +00:00
|
|
|
/**
|
|
|
|
* Internal method that updates the data and path values.
|
|
|
|
*
|
|
|
|
* @method Phaser.GameObjects.Arc#updateData
|
|
|
|
* @private
|
|
|
|
* @since 3.13.0
|
|
|
|
*
|
|
|
|
* @return {this} This Game Object instance.
|
|
|
|
*/
|
2018-09-05 15:20:25 +00:00
|
|
|
updateData: function ()
|
|
|
|
{
|
2018-09-07 11:09:57 +00:00
|
|
|
var step = this._iterations;
|
2018-09-05 15:20:25 +00:00
|
|
|
var iteration = step;
|
|
|
|
|
2018-09-12 11:37:18 +00:00
|
|
|
var radius = this.geom.radius;
|
2018-09-07 11:09:57 +00:00
|
|
|
var startAngle = DegToRad(this._startAngle);
|
|
|
|
var endAngle = DegToRad(this._endAngle);
|
|
|
|
var anticlockwise = this._anticlockwise;
|
2018-09-05 15:20:25 +00:00
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
var x = radius / 2;
|
|
|
|
var y = radius / 2;
|
|
|
|
|
2018-09-05 15:20:25 +00:00
|
|
|
endAngle -= startAngle;
|
|
|
|
|
|
|
|
if (anticlockwise)
|
|
|
|
{
|
|
|
|
if (endAngle < -MATH_CONST.PI2)
|
|
|
|
{
|
|
|
|
endAngle = -MATH_CONST.PI2;
|
|
|
|
}
|
|
|
|
else if (endAngle > 0)
|
|
|
|
{
|
|
|
|
endAngle = -MATH_CONST.PI2 + endAngle % MATH_CONST.PI2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (endAngle > MATH_CONST.PI2)
|
|
|
|
{
|
|
|
|
endAngle = MATH_CONST.PI2;
|
|
|
|
}
|
|
|
|
else if (endAngle < 0)
|
|
|
|
{
|
|
|
|
endAngle = MATH_CONST.PI2 + endAngle % MATH_CONST.PI2;
|
|
|
|
}
|
|
|
|
|
|
|
|
var path = [ x + Math.cos(startAngle) * radius, y + Math.sin(startAngle) * radius ];
|
|
|
|
|
|
|
|
var ta;
|
|
|
|
|
|
|
|
while (iteration < 1)
|
|
|
|
{
|
|
|
|
ta = endAngle * iteration + startAngle;
|
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
path.push(x + Math.cos(ta) * radius, y + Math.sin(ta) * radius);
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
iteration += step;
|
|
|
|
}
|
|
|
|
|
|
|
|
ta = endAngle + startAngle;
|
|
|
|
|
2018-09-06 14:49:42 +00:00
|
|
|
path.push(x + Math.cos(ta) * radius, y + Math.sin(ta) * radius);
|
|
|
|
|
|
|
|
path.push(x + Math.cos(startAngle) * radius, y + Math.sin(startAngle) * radius);
|
2018-09-05 15:20:25 +00:00
|
|
|
|
|
|
|
this.pathIndexes = Earcut(path);
|
|
|
|
this.pathData = path;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = Arc;
|