Skip to content

Commit ce32d49

Browse files
committed
Phaser.Polygon has been refactored to address some Pixi v2 migration issues (thanks @pnstickne for the original implementation phaserjs#1267)
Polygon.area is now only calculated when the Polygon points list is modified, rather than on every call. Phaser.Polygon can now accept the points list in a variety of formats: Arrays of Points, numbers, objects with public x/y properties or any combination of, or as a parameter list (thanks @pnstickne for the original implementation phaserjs#1267) Polygon.contains now correctly calculates the result (thanks @pnstickne @BurnedToast phaserjs#1267)
1 parent dc20ab6 commit ce32d49

3 files changed

Lines changed: 136 additions & 132 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ Version 2.1.4 - "Bethal" - in development
9191
* Game.destroy now destroys either the WebGLRenderer or CanvasRenderer, whichever Pixi was using.
9292
* Particle.Emitter will now automatically set `particle.body.skipQuadTree` to `true` to help with collision speeds within Arcade Physics.
9393
* Particle.Emitter.explode (or `Emitter.start` with the `explode` parameter set to `true`) will immediately emit the required quantity of particles and not delay until the next frame to do so. This means you can re-use a single emitter across multiple places in your game that require explode-style emissions, just by adjusting the `emitter.x` and `emitter.y` properties before calling explode (thanks Insanehero)
94+
* Phaser.Polygon has been refactored to address some Pixi v2 migration issues (thanks @pnstickne for the original implementation #1267)
95+
* Polygon.area is now only calculated when the Polygon points list is modified, rather than on every call.
96+
* Phaser.Polygon can now accept the points list in a variety of formats: Arrays of Points, numbers, objects with public x/y properties or any combination of, or as a parameter list (thanks @pnstickne for the original implementation #1267)
9497

9598
### Bug Fixes
9699

@@ -100,6 +103,8 @@ Version 2.1.4 - "Bethal" - in development
100103
* Loader.json was using the wrong context in IE9 with XDomainRequest calls (thanks @pnstickne #1258)
101104
* Polygon.contains was toggling the return value on each valid hit (thanks @Singularetantum #1265 #1266)
102105
* Text.updateText was incorrectly increasing the size of the texture each time it was called (thanks @spayton #1261)
106+
* Polygon.contains now correctly calculates the result (thanks @pnstickne @BurnedToast #1267)
107+
* Setting Key.enabled = false while it is down did not reset the isDown state (thanks @pnstickne #1190 #1271)
103108

104109

105110
For details about changes made in previous versions of Phaser see the full Change Log at https://github.com/photonstorm/phaser/blob/master/CHANGELOG.md

build/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
echo <<<EOL
3838
3939
<script src="$path/src/pixi/Pixi.js"></script>
40-
<script src="$path/src/pixi/geom/Polygon.js"></script>
4140
<script src="$path/src/pixi/geom/Matrix.js"></script>
41+
<script src="$path/src/pixi/geom/Polygon.js"></script>
4242
<script src="$path/src/pixi/display/DisplayObject.js"></script>
4343
<script src="$path/src/pixi/display/DisplayObjectContainer.js"></script>
4444
<script src="$path/src/pixi/display/Sprite.js"></script>

src/geom/Polygon.js

Lines changed: 130 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,43 @@
66
*/
77

88
/**
9-
* Creates a new Polygon. You have to provide a list of points.
10-
* This can be an array of Points that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...],
11-
* or the arguments passed can be all the points of the polygon e.g. `new Phaser.Polygon(new Phaser.Point(), new Phaser.Point(), ...)`, or the
12-
* arguments passed can be flat x,y values e.g. `new Phaser.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are numbers.
9+
* Creates a new Polygon.
10+
*
11+
* The points can be set from a variety of formats:
12+
*
13+
* - An array of Point objects: `[new Phaser.Point(x1, y1), ...]`
14+
* - An array of objects with public x/y properties: `[obj1, obj2, ...]`
15+
* - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]`
16+
* - As separate Point arguments: `setTo(new Phaser.Point(x1, y1), ...)`
17+
* - As separate objects with public x/y properties arguments: `setTo(obj1, obj2, ...)`
18+
* - As separate arguments representing point coordinates: `setTo(x1,y1, x2,y2, ...)`
1319
*
1420
* @class Phaser.Polygon
1521
* @constructor
16-
* @param {Phaser.Point[]|number[]} points - The array of Points.
22+
* @param {Phaser.Point[]|number[]|...Phaser.Point|...number} points - The points to set.
1723
*/
18-
Phaser.Polygon = function (points) {
24+
Phaser.Polygon = function () {
1925

2026
/**
21-
* @property {number} type - The base object type.
22-
*/
27+
* @property {number} type - The base object type.
28+
*/
2329
this.type = Phaser.POLYGON;
2430

25-
// If points isn't an array, use arguments as the array
26-
if (!(points instanceof Array))
27-
{
28-
points = Array.prototype.slice.call(arguments);
29-
}
30-
31-
// If this is a flat array of numbers, convert it to points
32-
if (points[0] instanceof Phaser.Point)
33-
{
34-
var p = [];
35-
36-
for (var i = 0, il = points.length; i < il; i++)
37-
{
38-
p.push(points[i].x, points[i].y);
39-
}
40-
41-
points = p;
42-
}
31+
/**
32+
* @property {number} area - The area of this Polygon.
33+
*/
34+
this.area = 0;
4335

4436
/**
45-
* @property {array} points - An array of Points that make up this Polygon.
37+
* @property {array} _points - An array of Points that make up this Polygon.
38+
* @private
4639
*/
47-
this.points = points;
40+
this._points = [];
41+
42+
if (arguments.length > 0)
43+
{
44+
this.setTo.apply(this, arguments);
45+
}
4846

4947
/**
5048
* @property {boolean} closed - Is the Polygon closed or not?
@@ -60,12 +58,12 @@ Phaser.Polygon.prototype = {
6058
* This is a deep clone, the resulting copy contains new Phaser.Point objects
6159
*
6260
* @method Phaser.Polygon#clone
63-
* @param {Phaser.Polygon} [output] Optional Polygon object. If given the values will be set into this object, otherwise a brand new Polygon object will be created and returned.
64-
* @return {Phaser.Polygon} The new Polygon object.
61+
* @param {Phaser.Polygon} [output=(new Polygon)] - The polygon to update. If not specified a new polygon will be created.
62+
* @return {Phaser.Polygon} The cloned (`output`) polygon object.
6563
*/
6664
clone: function (output) {
6765

68-
var points = this.points.slice();
66+
var points = this._points.slice();
6967

7068
if (typeof output === "undefined" || output === null)
7169
{
@@ -90,155 +88,156 @@ Phaser.Polygon.prototype = {
9088
*/
9189
contains: function (x, y) {
9290

93-
// use some raycasting to test hits https://github.com/substack/point-in-polygon/blob/master/index.js
91+
// Adapted from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html by Jonas Raoni Soares Silva
9492

95-
var length = this.points.length / 2;
93+
var length = this._points.length;
94+
var inside = false;
9695

97-
for (var i = 0, j = length - 1; i < length; j = i++)
96+
for (var i = -1, j = length - 1; ++i < length; j = i)
9897
{
99-
var xi = this.points[i * 2].x;
100-
var yi = this.points[i * 2 + 1].y;
101-
var xj = this.points[j * 2].x;
102-
var yj = this.points[j * 2 + 1].y;
98+
var ix = this._points[i].x;
99+
var iy = this._points[i].y;
103100

104-
var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
101+
var jx = this._points[j].x;
102+
var jy = this._points[j].y;
105103

106-
if (intersect)
107-
{
108-
return true;
109-
}
104+
((iy <= y && y < jy) || (jy <= y && y < iy)) && (x < (jx - ix) * (y - iy) / (jy - iy) + ix) && (inside = !inside);
110105
}
111106

112-
return false;
107+
return inside;
113108

114109
},
115110

116111
/**
117-
* Sets this Polygon to the given points.
118-
*
119-
* @method Phaser.Polygon#setTo
120-
* @param {Phaser.Point[]|number[]} points - The array of Points.
121-
* @return {boolean} True if the coordinates are within this polygon, otherwise false.
122-
*/
112+
* Sets this Polygon to the given points.
113+
*
114+
* The points can be set from a variety of formats:
115+
*
116+
* - An array of Point objects: `[new Phaser.Point(x1, y1), ...]`
117+
* - An array of objects with public x/y properties: `[obj1, obj2, ...]`
118+
* - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]`
119+
* - As separate Point arguments: `setTo(new Phaser.Point(x1, y1), ...)`
120+
* - As separate objects with public x/y properties arguments: `setTo(obj1, obj2, ...)`
121+
* - As separate arguments representing point coordinates: `setTo(x1,y1, x2,y2, ...)`
122+
*
123+
* `setTo` may also be called without any arguments to remove all points.
124+
*
125+
* @method Phaser.Polygon#setTo
126+
* @param {Phaser.Point[]|number[]|...Phaser.Point|...number} points - The points to set.
127+
* @return {Phaser.Polygon} This Polygon object
128+
*/
123129
setTo: function (points) {
124130

125-
// If points isn't an array, use arguments as the array
126-
if (!(points instanceof Array))
127-
{
128-
points = Array.prototype.slice.call(arguments);
129-
}
131+
this.area = 0;
132+
this._points = [];
130133

131-
// If this is a flat array of numbers, convert it to points
132-
if (points[0] instanceof Phaser.Point)
134+
if (arguments.length > 0)
133135
{
134-
var p = [];
136+
// If points isn't an array, use arguments as the array
137+
if (!Array.isArray(points))
138+
{
139+
points = Array.prototype.slice.call(arguments);
140+
}
141+
142+
var y0 = Number.MAX_VALUE;
135143

136-
for (var i = 0, il = points.length; i < il; i++)
144+
// Allows for mixed-type arguments
145+
for (var i = 0, len = points.length; i < len; i++)
137146
{
138-
p.push(points[i].x, points[i].y);
147+
if (typeof points[i] === 'number')
148+
{
149+
var p = new Phaser.Point(points[i], points[i + 1]);
150+
i++;
151+
}
152+
else
153+
{
154+
var p = new Phaser.Point(points[i].x, points[i].y);
155+
}
156+
157+
this._points.push(p);
158+
159+
// Lowest boundary
160+
if (p.y < y0)
161+
{
162+
y0 = p.y;
163+
}
139164
}
140165

141-
points = p;
166+
this.calculateArea(y0);
142167
}
143168

144-
this.points = points;
145-
146169
return this;
147170

148-
}
149-
150-
};
151-
152-
Phaser.Polygon.prototype.constructor = Phaser.Polygon;
153-
154-
/*
155-
* Sets and modifies the points of this polygon.
156-
*
157-
* @name Phaser.Polygon#points
158-
* @property {array<Phaser.Point>|array<number>} points - The array of vertex points
159-
*/
160-
Object.defineProperty(Phaser.Polygon.prototype, 'points', {
161-
162-
get: function() {
163-
return this._points;
164171
},
165172

166-
set: function(points) {
173+
/**
174+
* Calcuates the area of the Polygon. This is available in the property Polygon.area
175+
*
176+
* @method Phaser.Polygon#calculateArea
177+
* @private
178+
* @param {number} y0 - The lowest boundary
179+
* @return {number} The area of the Polygon.
180+
*/
181+
calculateArea: function (y0) {
167182

168-
//if points isn't an array, use arguments as the array
169-
if (!(points instanceof Array))
170-
{
171-
points = Array.prototype.slice.call(arguments);
172-
}
183+
var p1;
184+
var p2;
185+
var avgHeight;
186+
var width;
173187

174-
//if this is a flat array of numbers, convert it to points
175-
if (typeof points[0] === 'number')
188+
for (var i = 0, len = this._points.length; i < len; i++)
176189
{
177-
var p = [];
190+
p1 = this._points[i];
178191

179-
for (var i = 0, len = points.length; i < len; i += 2)
192+
if (i === len - 1)
180193
{
181-
p.push(new Phaser.Point(points[i], points[i + 1]));
194+
p2 = this._points[0];
195+
}
196+
else
197+
{
198+
p2 = this._points[i + 1];
182199
}
183200

184-
points = p;
201+
avgHeight = ((p1.y - y0) + (p2.y - y0)) / 2;
202+
width = p1.x - p2.x;
203+
this.area += avgHeight * width;
185204
}
186205

187-
this._points = points;
206+
return this.area;
207+
188208
}
189209

190-
});
210+
};
211+
212+
Phaser.Polygon.prototype.constructor = Phaser.Polygon;
191213

192214
/**
193-
* Returns the area of the polygon.
215+
* Sets and modifies the points of this polygon.
194216
*
195-
* @name Phaser.Polygon#area
196-
* @readonly
217+
* See {@link Phaser.Polygon#setTo setTo} for the different kinds of arrays formats that can be assigned.
218+
*
219+
* @name Phaser.Polygon#points
220+
* @property {Phaser.Point[]} points - The array of vertex points.
221+
* @deprecated Use `setTo`.
197222
*/
198-
Object.defineProperty(Phaser.Polygon.prototype, 'area', {
223+
Object.defineProperty(Phaser.Polygon.prototype, 'points', {
199224

200225
get: function() {
226+
return this._points;
227+
},
201228

202-
var p1;
203-
var p2;
204-
var avgHeight;
205-
var width;
206-
var i;
207-
var y0 = Number.MAX_VALUE;
208-
var area = 0;
229+
set: function(points) {
209230

210-
// Find lowest boundary
211-
for (i = 0; i < this.points.length; i++)
231+
if (points != null)
212232
{
213-
if (this.points[i].y < y0)
214-
{
215-
y0 = this.points[i].y;
216-
}
233+
this.setTo(points);
217234
}
218-
219-
for (i = 0; i< this.points.length; i++)
235+
else
220236
{
221-
p1 = this.points[i];
222-
223-
if (i === this.points.length - 1)
224-
{
225-
p2 = this.points[0];
226-
}
227-
else
228-
{
229-
p2 = this.points[i+1];
230-
}
231-
232-
avgHeight = ((p1.y - y0) + (p2.y - y0)) / 2;
233-
width = p1.x - p2.x;
234-
area += avgHeight * width;
237+
// Clear the points
238+
this.setTo();
235239
}
236240

237-
return area;
238-
239241
}
240242

241243
});
242-
243-
// Because PIXI uses its own Polygon, we'll replace it with ours to avoid duplicating code or confusion.
244-
// PIXI.Polygon = Phaser.Polygon;

0 commit comments

Comments
 (0)