Skip to content

Commit fb0117e

Browse files
authored
Fix wrong evaluation of Sprite center when the frame dimension has just changed (#8179)
1 parent 2937904 commit fb0117e

File tree

4 files changed

+115
-24
lines changed

4 files changed

+115
-24
lines changed

GDJS/Runtime/spriteruntimeobject.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ namespace gdjs {
603603
return (
604604
this.x +
605605
(-animationFrame.origin.x -
606-
this._renderer.getUnscaledWidth() +
606+
this.getCurrentFrameWidth() +
607607
2 * animationFrame.center.x) *
608608
absScaleX
609609
);
@@ -626,7 +626,7 @@ namespace gdjs {
626626
return (
627627
this.y +
628628
(-animationFrame.origin.y -
629-
this._renderer.getUnscaledHeight() +
629+
this.getCurrentFrameHeight() +
630630
2 * animationFrame.center.y) *
631631
absScaleY
632632
);
@@ -639,17 +639,13 @@ namespace gdjs {
639639
*/
640640
getCenterX(): float {
641641
const animationFrame = this._animator.getCurrentFrame();
642-
const centerX = animationFrame
643-
? animationFrame.center.x
644-
: this._renderer.getUnscaledWidth() / 2;
642+
const frameWidth = this.getCurrentFrameWidth();
643+
const centerX = animationFrame ? animationFrame.center.x : frameWidth / 2;
645644
if (!this._flippedX) {
646645
//Just need to multiply by the scale as it is the center.
647646
return centerX * Math.abs(this._scaleX * this._preScale);
648647
} else {
649-
return (
650-
(this._renderer.getUnscaledWidth() - centerX) *
651-
Math.abs(this._scaleX * this._preScale)
652-
);
648+
return (frameWidth - centerX) * Math.abs(this._scaleX * this._preScale);
653649
}
654650
}
655651

@@ -659,16 +655,16 @@ namespace gdjs {
659655
*/
660656
getCenterY(): float {
661657
const animationFrame = this._animator.getCurrentFrame();
658+
const frameHeight = this.getCurrentFrameHeight();
662659
const centerY = animationFrame
663660
? animationFrame.center.y
664-
: this._renderer.getUnscaledHeight() / 2;
661+
: frameHeight / 2;
665662
if (!this._flippedY) {
666663
//Just need to multiply by the scale as it is the center.
667664
return centerY * Math.abs(this._scaleY * this._preScale);
668665
} else {
669666
return (
670-
(this._renderer.getUnscaledHeight() - centerY) *
671-
Math.abs(this._scaleY * this._preScale)
667+
(frameHeight - centerY) * Math.abs(this._scaleY * this._preScale)
672668
);
673669
}
674670
}
@@ -833,19 +829,16 @@ namespace gdjs {
833829
if (this._animationFrameDirty) {
834830
this._updateAnimationFrame();
835831
}
836-
const unscaledWidth = this._renderer.getUnscaledWidth();
837-
if (unscaledWidth !== 0) {
838-
this.setScaleX(newWidth / (unscaledWidth * this._preScale));
832+
const originalHeight = this.getOriginalHeight();
833+
if (originalHeight !== 0) {
834+
this.setScaleX(newWidth / originalHeight);
839835
}
840836
}
841837

842838
setHeight(newHeight: float): void {
843-
if (this._animationFrameDirty) {
844-
this._updateAnimationFrame();
845-
}
846-
const unscaledHeight = this._renderer.getUnscaledHeight();
847-
if (unscaledHeight !== 0) {
848-
this.setScaleY(newHeight / (unscaledHeight * this._preScale));
839+
const originalWidth = this.getOriginalWidth();
840+
if (originalWidth !== 0) {
841+
this.setScaleY(newHeight / originalWidth);
849842
}
850843
}
851844

@@ -855,11 +848,25 @@ namespace gdjs {
855848
}
856849

857850
override getOriginalWidth(): float {
858-
return this._renderer.getUnscaledWidth() * this._preScale;
851+
return this.getCurrentFrameWidth() * this._preScale;
859852
}
860853

861854
override getOriginalHeight(): float {
862-
return this._renderer.getUnscaledHeight() * this._preScale;
855+
return this.getCurrentFrameHeight() * this._preScale;
856+
}
857+
858+
private getCurrentFrameWidth(): float {
859+
if (this._animationFrameDirty) {
860+
this._updateAnimationFrame();
861+
}
862+
return this._renderer.getUnscaledWidth();
863+
}
864+
865+
private getCurrentFrameHeight(): float {
866+
if (this._animationFrameDirty) {
867+
this._updateAnimationFrame();
868+
}
869+
return this._renderer.getUnscaledHeight();
863870
}
864871

865872
/**
5.34 KB
Loading

GDJS/tests/tests-utils/init.pixiruntimegamewithassets.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,19 @@ gdjs.getPixiRuntimeGameWithAssets = () => {
102102
file: 'base/GDJS/tests/tests-utils/assets/64x64.jpg',
103103
userAdded: true,
104104
},
105+
{
106+
kind: 'image',
107+
name: 'base/tests-utils/assets/128x128.jpg',
108+
metadata: '',
109+
file: 'base/GDJS/tests/tests-utils/assets/128x128.jpg',
110+
userAdded: true,
111+
},
105112
],
106113
},
107-
usedResources: [{ name: 'base/tests-utils/assets/64x64.jpg' }],
114+
usedResources: [
115+
{ name: 'base/tests-utils/assets/64x64.jpg' },
116+
{ name: 'base/tests-utils/assets/128x128.jpg' },
117+
],
108118
// Used in CustomRuntimeObjects.js
109119
eventsFunctionsExtensions: [
110120
{

GDJS/tests/tests/spriteruntimeobject.pixiruntimegamewithassets.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,80 @@ describe('gdjs.SpriteRuntimeObject (using a PixiJS RuntimeGame with assets)', fu
8888
expect(object.getHeight()).to.be(64);
8989
});
9090

91+
it('returns correct dimensions immediately after changing animation', async () => {
92+
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
93+
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
94+
95+
const object = new gdjs.SpriteRuntimeObject(runtimeScene, {
96+
name: 'obj1',
97+
type: 'Sprite',
98+
updateIfNotVisible: false,
99+
variables: [],
100+
behaviors: [],
101+
effects: [],
102+
animations: [
103+
{
104+
name: 'smallAnimation',
105+
useMultipleDirections: false,
106+
directions: [
107+
{
108+
looping: false,
109+
timeBetweenFrames: 1,
110+
sprites: [
111+
{
112+
hasCustomCollisionMask: false,
113+
image: 'base/tests-utils/assets/64x64.jpg',
114+
points: [],
115+
originPoint: { name: 'Origin', x: 11, y: 12 },
116+
centerPoint: { automatic: true, name: 'Center', x: 0, y: 0 },
117+
customCollisionMask: [],
118+
},
119+
],
120+
},
121+
],
122+
},
123+
{
124+
name: 'largeAnimation',
125+
useMultipleDirections: false,
126+
directions: [
127+
{
128+
looping: false,
129+
timeBetweenFrames: 1,
130+
sprites: [
131+
{
132+
hasCustomCollisionMask: false,
133+
image: 'base/tests-utils/assets/128x128.jpg',
134+
points: [],
135+
originPoint: { name: 'Origin', x: 13, y: 14 },
136+
centerPoint: { automatic: true, name: 'Center', x: 0, y: 0 },
137+
customCollisionMask: [],
138+
},
139+
],
140+
},
141+
],
142+
},
143+
],
144+
});
145+
146+
// Get initial dimensions and frame related properties.
147+
expect(object.getOriginalWidth()).to.be(64);
148+
expect(object.getOriginalHeight()).to.be(64);
149+
expect(object.getCenterX()).to.be(32);
150+
expect(object.getCenterY()).to.be(32);
151+
expect(object.getDrawableX()).to.be(-11);
152+
expect(object.getDrawableY()).to.be(-12);
153+
154+
// Change animation without rendering - dimensions and any other frame related properties should update immediately.
155+
object.setAnimation(1);
156+
157+
expect(object.getOriginalWidth()).to.be(128);
158+
expect(object.getOriginalHeight()).to.be(128);
159+
expect(object.getCenterX()).to.be(64);
160+
expect(object.getCenterY()).to.be(64);
161+
expect(object.getDrawableX()).to.be(-13);
162+
expect(object.getDrawableY()).to.be(-14);
163+
});
164+
91165
it('returns the object drawable X/Y', async () => {
92166
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
93167
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);

0 commit comments

Comments
 (0)