Skip to content

Commit c5f6817

Browse files
committed
Working sprite bounds / vertices regardless of scale or rotation
1 parent 1f8c809 commit c5f6817

21 files changed

Lines changed: 1702 additions & 187 deletions

Phaser/components/Transform.ts

Lines changed: 170 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,44 +27,135 @@ module Phaser.Components {
2727

2828
}
2929

30-
private _sin: number;
31-
private _cos: number;
30+
private _rotation: number;
31+
32+
private _cachedSin: number;
33+
private _cachedCos: number;
34+
private _cachedRotation: number;
35+
private _cachedScaleX: number;
36+
private _cachedScaleY: number;
37+
private _cachedAngle: number;
38+
private _cachedAngleToCenter: number;
39+
private _cachedDistance: number;
40+
private _cachedWidth: number;
41+
private _cachedHeight: number;
42+
private _cachedHalfWidth: number;
43+
private _cachedHalfHeight: number;
44+
private _cachedCosAngle: number;
45+
private _cachedSinAngle: number;
46+
private _cachedOffsetX: number;
47+
private _cachedOffsetY: number;
48+
private _cachedOriginX: number;
49+
private _cachedOriginY: number;
50+
private _cachedCenterX: number;
51+
private _cachedCenterY: number;
3252

3353
public local: Mat3;
3454

55+
public setCache() {
56+
57+
this._cachedHalfWidth = this.parent.width / 2;
58+
this._cachedHalfHeight = this.parent.height / 2;
59+
this._cachedOffsetX = this.origin.x * this.parent.width;
60+
this._cachedOffsetY = this.origin.y * this.parent.height;
61+
this._cachedAngleToCenter = Math.atan2(this.halfHeight - this._cachedOffsetY, this.halfWidth - this._cachedOffsetX);
62+
this._cachedDistance = Math.sqrt(((this._cachedOffsetX - this._cachedHalfWidth) * (this._cachedOffsetX - this._cachedHalfWidth)) + ((this._cachedOffsetY - this._cachedHalfHeight) * (this._cachedOffsetY - this._cachedHalfHeight)));
63+
this._cachedWidth = this.parent.width;
64+
this._cachedHeight = this.parent.height;
65+
this._cachedOriginX = this.origin.x;
66+
this._cachedOriginY = this.origin.y;
67+
this._cachedSin = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
68+
this._cachedCos = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
69+
this._cachedCosAngle = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD + this._cachedAngleToCenter);
70+
this._cachedSinAngle = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD + this._cachedAngleToCenter);
71+
this._cachedRotation = this.rotation;
72+
73+
if (this.parent.texture && this.parent.texture.renderRotation)
74+
{
75+
this._cachedSin = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
76+
this._cachedCos = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
77+
}
78+
else
79+
{
80+
this._cachedSin = 0;
81+
this._cachedCos = 1;
82+
}
83+
84+
}
85+
3586
public update() {
3687

37-
// Scale & Skew
88+
// Check cache
89+
var dirty: bool = false;
3890

39-
this._sin = 0;
40-
this._cos = 1;
91+
// 1) Height or Width change (also triggered by a change in scale) or an Origin change
92+
if (this.parent.width !== this._cachedWidth || this.parent.height !== this._cachedHeight || this.origin.x !== this._cachedOriginX|| this.origin.y !== this._cachedOriginY)
93+
{
94+
this._cachedHalfWidth = this.parent.width / 2;
95+
this._cachedHalfHeight = this.parent.height / 2;
96+
this._cachedOffsetX = this.origin.x * this.parent.width;
97+
this._cachedOffsetY = this.origin.y * this.parent.height;
98+
this._cachedAngleToCenter = Math.atan2(this.halfHeight - this._cachedOffsetY, this.halfWidth - this._cachedOffsetX);
99+
this._cachedDistance = Math.sqrt(((this._cachedOffsetX - this._cachedHalfWidth) * (this._cachedOffsetX - this._cachedHalfWidth)) + ((this._cachedOffsetY - this._cachedHalfHeight) * (this._cachedOffsetY - this._cachedHalfHeight)));
100+
// Store
101+
this._cachedWidth = this.parent.width;
102+
this._cachedHeight = this.parent.height;
103+
this._cachedOriginX = this.origin.x;
104+
this._cachedOriginY = this.origin.y;
105+
dirty = true;
106+
}
107+
108+
// 2) Rotation change
109+
if (this.rotation != this._cachedRotation)
110+
{
111+
this._cachedSin = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
112+
this._cachedCos = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
113+
this._cachedCosAngle = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD + this._cachedAngleToCenter);
114+
this._cachedSinAngle = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD + this._cachedAngleToCenter);
115+
116+
if (this.parent.texture.renderRotation)
117+
{
118+
this._cachedSin = Math.sin((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
119+
this._cachedCos = Math.cos((this.rotation + this.rotationOffset) * GameMath.DEG_TO_RAD);
120+
}
121+
else
122+
{
123+
this._cachedSin = 0;
124+
this._cachedCos = 1;
125+
}
126+
127+
// Store
128+
this._cachedRotation = this.rotation;
129+
dirty = true;
130+
}
41131

42-
if (this.parent.texture.renderRotation)
132+
if (dirty)
43133
{
44-
this._sin = GameMath.sinA[this.rotation + this.rotationOffset];
45-
this._cos = GameMath.cosA[this.rotation + this.rotationOffset];
134+
this._cachedCenterX = this.parent.x + this._cachedDistance * this._cachedCosAngle;
135+
this._cachedCenterY = this.parent.y + this._cachedDistance * this._cachedSinAngle;
46136
}
47137

138+
// Scale and Skew
48139
if (this.parent.texture.flippedX)
49140
{
50-
this.local.data[0] = this._cos * -this.scale.x;
51-
this.local.data[3] = (this._sin * -this.scale.x) + this.skew.x;
141+
this.local.data[0] = this._cachedCos * -this.scale.x;
142+
this.local.data[3] = (this._cachedSin * -this.scale.x) + this.skew.x;
52143
}
53144
else
54145
{
55-
this.local.data[0] = this._cos * this.scale.x;
56-
this.local.data[3] = (this._sin * this.scale.x) + this.skew.x;
146+
this.local.data[0] = this._cachedCos * this.scale.x;
147+
this.local.data[3] = (this._cachedSin * this.scale.x) + this.skew.x;
57148
}
58149

59150
if (this.parent.texture.flippedY)
60151
{
61-
this.local.data[4] = this._cos * -this.scale.y;
62-
this.local.data[1] = -(this._sin * -this.scale.y) + this.skew.y;
152+
this.local.data[4] = this._cachedCos * -this.scale.y;
153+
this.local.data[1] = -(this._cachedSin * -this.scale.y) + this.skew.y;
63154
}
64155
else
65156
{
66-
this.local.data[4] = this._cos * this.scale.y;
67-
this.local.data[1] = -(this._sin * this.scale.y) + this.skew.y;
157+
this.local.data[4] = this._cachedCos * this.scale.y;
158+
this.local.data[1] = -(this._cachedSin * this.scale.y) + this.skew.y;
68159
}
69160

70161
// Translate
@@ -99,7 +190,7 @@ module Phaser.Components {
99190
public scrollFactor: Phaser.Vec2;
100191

101192
/**
102-
* The origin is the point around which scale and rotation takes place and defaults to the center of the sprite.
193+
* The origin is the point around which scale and rotation takes place and defaults to the top-left of the sprite.
103194
*/
104195
public origin: Phaser.Vec2;
105196

@@ -117,17 +208,75 @@ module Phaser.Components {
117208
public rotation: number = 0;
118209

119210
/**
120-
* The center of the Sprite after taking scaling into consideration
211+
* The distance from the center of the transform to the rotation origin.
212+
*/
213+
public get distance(): number {
214+
return this._cachedDistance;
215+
//return Math.sqrt(((this.offsetX - this.halfWidth) * (this.offsetX - this.halfWidth)) + ((this.offsetY - this.halfHeight) * (this.offsetY - this.halfHeight)));
216+
}
217+
218+
/**
219+
* The angle between the center of the transform to the rotation origin.
220+
*/
221+
public get angleToCenter(): number {
222+
return this._cachedAngleToCenter;
223+
//return Math.atan2(this.halfHeight - this.offsetY, this.halfWidth - this.offsetX);
224+
}
225+
226+
/**
227+
* The offset on the X axis of the origin
228+
*/
229+
public get offsetX(): number {
230+
return this._cachedOffsetX;
231+
//return this.origin.x * this.parent.width;
232+
}
233+
234+
/**
235+
* The offset on the Y axis of the origin
236+
*/
237+
public get offsetY(): number {
238+
return this._cachedOffsetY;
239+
//return this.origin.y * this.parent.height;
240+
}
241+
242+
/**
243+
* Half the width of the parent sprite, taking into consideration scaling
244+
*/
245+
public get halfWidth(): number {
246+
return this._cachedHalfWidth;
247+
//return this.parent.width / 2;
248+
}
249+
250+
/**
251+
* Half the height of the parent sprite, taking into consideration scaling
252+
*/
253+
public get halfHeight(): number {
254+
return this._cachedHalfHeight;
255+
//return this.parent.height / 2;
256+
}
257+
258+
/**
259+
* The center of the Sprite in world coordinates, after taking scaling and rotation into consideration
121260
*/
122261
public get centerX(): number {
123-
return this.parent.width / 2;
262+
return this._cachedCenterX;
263+
//return this.parent.x + this.distance * Math.cos((this.rotation * Math.PI / 180) + this.angleToCenter);
124264
}
125265

126266
/**
127-
* The center of the Sprite after taking scaling into consideration
267+
* The center of the Sprite in world coordinates, after taking scaling and rotation into consideration
128268
*/
129269
public get centerY(): number {
130-
return this.parent.height / 2;
270+
return this._cachedCenterY;
271+
//return this.parent.y + this.distance * Math.sin((this.rotation * Math.PI / 180) + this.angleToCenter);
272+
}
273+
274+
public get sin(): number {
275+
return this._cachedSin;
276+
}
277+
278+
public get cos(): number {
279+
return this._cachedCos;
131280
}
132281

133282
}

Phaser/gameobjects/Sprite.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ module Phaser {
7272
this.worldView = new Rectangle(x, y, this.width, this.height);
7373
this.cameraView = new Rectangle(x, y, this.width, this.height);
7474

75+
this.transform.setCache();
76+
7577
}
7678

7779
/**
@@ -243,8 +245,10 @@ module Phaser {
243245

244246
this.transform.update();
245247

246-
this.worldView.x = this.x * this.transform.scrollFactor.x;
247-
this.worldView.y = this.y * this.transform.scrollFactor.y;
248+
this.worldView.x = (this.x * this.transform.scrollFactor.x) - (this.width * this.transform.origin.x);
249+
this.worldView.y = (this.y * this.transform.scrollFactor.y) - (this.height * this.transform.origin.y);
250+
//this.worldView.x = this.x * this.transform.scrollFactor.x;
251+
//this.worldView.y = this.y * this.transform.scrollFactor.y;
248252
this.worldView.width = this.width;
249253
this.worldView.height = this.height;
250254

Phaser/renderers/CanvasRenderer.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ module Phaser {
221221
return true;
222222
}
223223

224-
Phaser.SpriteUtils.updateCameraView(camera, sprite);
225-
226224
return RectangleUtils.intersects(sprite.cameraView, camera.screenView);
227225

228226
}
@@ -447,7 +445,7 @@ module Phaser {
447445

448446
if (sprite.transform.scale.x == 0 || sprite.transform.scale.y == 0 || sprite.texture.alpha < 0.1 || this.inCamera(camera, sprite) == false)
449447
{
450-
//return false;
448+
return false;
451449
}
452450

453451
sprite.renderOrderID = this._count;

0 commit comments

Comments
 (0)