From ec3b8c54497797096821d3a871208d756c0ea49b Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Fri, 3 Jan 2025 03:51:54 +0400 Subject: [PATCH 1/9] add FlxG.center() and FlxCamera.center() --- flixel/FlxCamera.hx | 44 +++++++++++++++ flixel/FlxG.hx | 47 +++++++++++++++- flixel/FlxObject.hx | 15 ++---- tests/unit/src/flixel/FlxCameraTest.hx | 75 +++++++++++++++++++++++++- tests/unit/src/flixel/FlxGTest.hx | 67 +++++++++++++++++++++++ tests/unit/src/flixel/FlxObjectTest.hx | 9 ++-- 6 files changed, 241 insertions(+), 16 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 6a29052544..39604eb47f 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1901,6 +1901,50 @@ class FlxCamera extends FlxBasic setScale(scaleX, scaleY); } + /** + * Centers `FlxSprite` by graphic size in this camera view, either by the x axis, y axis, or both. + * + * @param sprite The sprite to center. + * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. + * @return Centered sprite for chaining. + * @since TBA + */ + public function center(sprite:T, axes:FlxAxes = XY):T + { + if (axes.x) + { + final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); + sprite.x = viewX + (viewWidth - graphicWidth) / 2; + } + + if (axes.y) + { + final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); + sprite.y = viewY + (viewHeight - graphicHeight) / 2; + } + + return sprite; + } + + /** + * Centers `FlxObject` by hitbox size in this camera view, either by the x axis, y axis, or both. + * + * @param sprite The object to center. + * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. + * @return Centered object for chaining. + * @since TBA + */ + public function centerHitbox(object:T, axes:FlxAxes = XY):T + { + if (axes.x) + object.x = viewX + (viewWidth - object.width) / 2; + + if (axes.y) + object.y = viewY + (viewHeight - object.height) / 2; + + return object; + } + /** * The size and position of this camera's margins, via `viewMarginLeft`, `viewMarginTop`, `viewWidth` * and `viewHeight`. diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 912532fdcb..c738c108a4 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -21,6 +21,7 @@ import flixel.system.frontEnds.VCRFrontEnd; import flixel.system.frontEnds.WatchFrontEnd; import flixel.system.scaleModes.BaseScaleMode; import flixel.system.scaleModes.RatioScaleMode; +import flixel.util.FlxAxes; import flixel.util.FlxCollision; import flixel.util.FlxSave; import flixel.util.typeLimit.NextState; @@ -510,7 +511,51 @@ class FlxG { return overlap(objectOrGroup1, objectOrGroup2, notifyCallback, FlxObject.separate); } - + + /** + * Centers `FlxSprite` by graphic size in game space, either by the x axis, y axis, or both. + * + * @param sprite The sprite to center. + * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. + * @return Centered sprite for chaining. + * @since TBA + */ + public static function center(sprite:T, axes:FlxAxes = XY):T + { + if (axes.x) + { + final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); + sprite.x = (FlxG.width - graphicWidth) / 2; + } + + if (axes.y) + { + final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); + sprite.y = (FlxG.height - graphicHeight) / 2; + } + + return sprite; + } + + /** + * Centers `FlxObject` by hitbox size in game space, either by the x axis, y axis, or both. + * + * @param sprite The object to center. + * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. + * @return Centered object for chaining. + * @since TBA + */ + public static function centerHitbox(object:T, axes:FlxAxes = XY):T + { + if (axes.x) + object.x = (FlxG.width - object.width) / 2; + + if (axes.y) + object.y = (FlxG.height - object.height) / 2; + + return object; + } + /** * Regular `DisplayObject`s are normally displayed over the Flixel cursor and the Flixel debugger if simply * added to `stage`. This function simplifies things by adding a `DisplayObject` directly below mouse level. diff --git a/flixel/FlxObject.hx b/flixel/FlxObject.hx index 21f5795b88..86adf8bdcf 100644 --- a/flixel/FlxObject.hx +++ b/flixel/FlxObject.hx @@ -1256,24 +1256,19 @@ class FlxObject extends FlxBasic kill(); } #end - + /** * Centers this `FlxObject` on the screen, either by the x axis, y axis, or both. - * + * * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return This FlxObject for chaining */ + @:deprecated("screenCenter is deprecated, use FlxG.centerHitbox instead") public inline function screenCenter(axes:FlxAxes = XY):FlxObject { - if (axes.x) - x = (FlxG.width - width) / 2; - - if (axes.y) - y = (FlxG.height - height) / 2; - - return this; + return FlxG.centerHitbox(this, axes); } - + /** * Helper function to set the coordinates of this object. * Handy since it only requires one line of code. diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 62eeb63819..5b2059a5e0 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -1,5 +1,6 @@ package flixel; +import flixel.math.FlxPoint; import flixel.util.FlxColor; import massive.munit.Assert; @@ -89,7 +90,79 @@ class FlxCameraTest extends FlxTest camera.follow(new FlxObject()); Assert.areEqual(defaultLerp, camera.followLerp); } - + + @Test + function testCenter() + { + final sprite = new FlxSprite(); + sprite.makeGraphic(10, 10); + sprite.scale.set(-2, -4); + final cam = FlxG.camera; + cam.scroll.set(100, 100); + cam.zoom *= 2; + final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); + final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); + final center = FlxPoint.get(cam.viewX + (cam.viewWidth - graphicWidth) / 2, cam.viewY + (cam.viewHeight - graphicHeight) / 2); + final offCenter = center.copyTo().add(1000, 1000); + + sprite.setPosition(offCenter.x, offCenter.y); + cam.center(sprite, X); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, offCenter.y); + + sprite.setPosition(offCenter.x, offCenter.y); + cam.center(sprite, Y); + Assert.areEqual(sprite.x, offCenter.x); + Assert.areEqual(sprite.y, center.y); + + sprite.setPosition(offCenter.x, offCenter.y); + cam.center(sprite, XY); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, center.y); + + sprite.setPosition(offCenter.x, offCenter.y); + cam.center(sprite); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, center.y); + + offCenter.put(); + center.put(); + } + + @Test + function testCenterHitbox() + { + final object = new FlxObject(0, 0, 10, 10); + final cam = FlxG.camera; + cam.scroll.set(100, 100); + cam.zoom *= 2; + final center = FlxPoint.get(cam.viewX + (cam.viewWidth - object.width) / 2, cam.viewY + (cam.viewHeight - object.height) / 2); + final offCenter = center.copyTo().add(1000, 1000); + + object.setPosition(offCenter.x, offCenter.y); + cam.centerHitbox(object, X); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, offCenter.y); + + object.setPosition(offCenter.x, offCenter.y); + cam.centerHitbox(object, Y); + Assert.areEqual(object.x, offCenter.x); + Assert.areEqual(object.y, center.y); + + object.setPosition(offCenter.x, offCenter.y); + cam.centerHitbox(object, XY); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, center.y); + + object.setPosition(offCenter.x, offCenter.y); + cam.centerHitbox(object); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, center.y); + + offCenter.put(); + center.put(); + } + @Test function testFadeInFadeOut() { diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 58d3daac76..b24082c5c0 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -1,5 +1,6 @@ package flixel; +import flixel.math.FlxPoint; import massive.munit.Assert; @:access(flixel.FlxG) @@ -104,4 +105,70 @@ class FlxGTest extends FlxTest { Assert.areEqual(480, FlxG.height); } + + @Test + function testCenter() + { + final sprite = new FlxSprite(); + sprite.makeGraphic(10, 10); + sprite.scale.set(-2, -4); + final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); + final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); + final center = FlxPoint.get((FlxG.width - graphicWidth) / 2, (FlxG.height - graphicHeight) / 2); + final offCenter = center.copyTo().add(1000, 1000); + + sprite.setPosition(offCenter.x, offCenter.y); + FlxG.center(sprite, X); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, offCenter.y); + + sprite.setPosition(offCenter.x, offCenter.y); + FlxG.center(sprite, Y); + Assert.areEqual(sprite.x, offCenter.x); + Assert.areEqual(sprite.y, center.y); + + sprite.setPosition(offCenter.x, offCenter.y); + FlxG.center(sprite, XY); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, center.y); + + sprite.setPosition(offCenter.x, offCenter.y); + FlxG.center(sprite); + Assert.areEqual(sprite.x, center.x); + Assert.areEqual(sprite.y, center.y); + + offCenter.put(); + center.put(); + } + + @Test + function testCenterHitbox() + { + final object = new FlxObject(0, 0, 10, 10); + final center = FlxPoint.get((FlxG.width - object.width) / 2, (FlxG.height - object.height) / 2); + final offCenter = center.copyTo().add(1000, 1000); + + object.setPosition(offCenter.x, offCenter.y); + FlxG.centerHitbox(object, X); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, offCenter.y); + + object.setPosition(offCenter.x, offCenter.y); + FlxG.centerHitbox(object, Y); + Assert.areEqual(object.x, offCenter.x); + Assert.areEqual(object.y, center.y); + + object.setPosition(offCenter.x, offCenter.y); + FlxG.centerHitbox(object, XY); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, center.y); + + object.setPosition(offCenter.x, offCenter.y); + FlxG.centerHitbox(object); + Assert.areEqual(object.x, center.x); + Assert.areEqual(object.y, center.y); + + offCenter.put(); + center.put(); + } } diff --git a/tests/unit/src/flixel/FlxObjectTest.hx b/tests/unit/src/flixel/FlxObjectTest.hx index 6fe89c7865..5454eb9285 100644 --- a/tests/unit/src/flixel/FlxObjectTest.hx +++ b/tests/unit/src/flixel/FlxObjectTest.hx @@ -341,6 +341,7 @@ class FlxObjectTest extends FlxTest } @Test + @:haxe.warning("-WDeprecated") // TODO: remove this test? function testScreenCenter() { var center = FlxPoint.get((FlxG.width - object1.width) / 2, (FlxG.height - object1.height) / 2); @@ -350,17 +351,17 @@ class FlxObjectTest extends FlxTest object1.screenCenter(X); Assert.areEqual(object1.x, center.x); Assert.areEqual(object1.y, offCenter.y); - + object1.setPosition(offCenter.x, offCenter.y); object1.screenCenter(Y); Assert.areEqual(object1.x, offCenter.x); Assert.areEqual(object1.y, center.y); - + object1.setPosition(offCenter.x, offCenter.y); object1.screenCenter(XY); Assert.areEqual(object1.x, center.x); Assert.areEqual(object1.y, center.y); - + object1.setPosition(offCenter.x, offCenter.y); object1.screenCenter(); Assert.areEqual(object1.x, center.x); @@ -369,7 +370,7 @@ class FlxObjectTest extends FlxTest offCenter.put(); center.put(); } - + @Test function testgetRotatedBounds() { From 5603edddada3dc95e96f5525c28e2f5d1f6eb061 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:45:16 +0400 Subject: [PATCH 2/9] use propper hitboxes --- flixel/FlxCamera.hx | 32 ++++++++++++++++++-------- flixel/FlxG.hx | 32 ++++++++++++++++++-------- tests/unit/src/flixel/FlxCameraTest.hx | 22 +++++++++++++----- tests/unit/src/flixel/FlxGTest.hx | 22 +++++++++++++----- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 2794537495..76dd620c3c 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1876,44 +1876,56 @@ class FlxCamera extends FlxBasic /** * Centers `FlxSprite` by graphic size in this camera view, either by the x axis, y axis, or both. * - * @param sprite The sprite to center. - * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. + * @param sprite The sprite to center. + * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered sprite for chaining. * @since TBA */ public function center(sprite:T, axes:FlxAxes = XY):T { + final graphicBounds = sprite.getScreenBounds(null, this); + if (axes.x) { - final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); - sprite.x = viewX + (viewWidth - graphicWidth) / 2; + final offset = sprite.x - graphicBounds.x; + sprite.x = (width - graphicBounds.width) / 2 + offset; } if (axes.y) { - final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); - sprite.y = viewY + (viewHeight - graphicHeight) / 2; + final offset = sprite.y - graphicBounds.y; + sprite.y = (height - graphicBounds.height) / 2 + offset; } + graphicBounds.put(); return sprite; } /** * Centers `FlxObject` by hitbox size in this camera view, either by the x axis, y axis, or both. * - * @param sprite The object to center. - * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. + * @param object The object to center. + * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered object for chaining. * @since TBA */ public function centerHitbox(object:T, axes:FlxAxes = XY):T { + final hitbox = object.getHitbox(); + if (axes.x) - object.x = viewX + (viewWidth - object.width) / 2; + { + final offset = object.x - hitbox.x; + object.x = scroll.x + (width - hitbox.width) / 2 + offset; + } if (axes.y) - object.y = viewY + (viewHeight - object.height) / 2; + { + final offset = object.y - hitbox.y; + object.y = scroll.y + (height - hitbox.height) / 2 + offset; + } + hitbox.put(); return object; } diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index b0e040f85a..443e4e0cd0 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -481,44 +481,56 @@ class FlxG /** * Centers `FlxSprite` by graphic size in game space, either by the x axis, y axis, or both. * - * @param sprite The sprite to center. - * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. + * @param sprite The sprite to center. + * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered sprite for chaining. * @since TBA */ public static function center(sprite:T, axes:FlxAxes = XY):T { + final graphicBounds = sprite.getGraphicBounds(); + if (axes.x) { - final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); - sprite.x = (FlxG.width - graphicWidth) / 2; + final offset = sprite.x - graphicBounds.x; + sprite.x = (FlxG.width - graphicBounds.width) / 2 + offset; } if (axes.y) { - final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); - sprite.y = (FlxG.height - graphicHeight) / 2; + final offset = sprite.y - graphicBounds.y; + sprite.y = (FlxG.height - graphicBounds.height) / 2 + offset; } + graphicBounds.put(); return sprite; } /** * Centers `FlxObject` by hitbox size in game space, either by the x axis, y axis, or both. * - * @param sprite The object to center. - * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. + * @param object The object to center. + * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered object for chaining. * @since TBA */ public static function centerHitbox(object:T, axes:FlxAxes = XY):T { + final hitbox = object.getHitbox(); + if (axes.x) - object.x = (FlxG.width - object.width) / 2; + { + final offset = object.x - hitbox.x; + object.x = (FlxG.width - hitbox.width) / 2 + offset; + } if (axes.y) - object.y = (FlxG.height - object.height) / 2; + { + final offset = object.y - hitbox.y; + object.y = (FlxG.height - hitbox.height) / 2 + offset; + } + hitbox.put(); return object; } diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 6a37fb43e2..51f287025a 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -95,14 +95,18 @@ class FlxCameraTest extends FlxTest function testCenter() { final sprite = new FlxSprite(); - sprite.makeGraphic(10, 10); - sprite.scale.set(-2, -4); + sprite.makeGraphic(100, 100); + sprite.origin.set(100, 100); + sprite.offset.set(100, 100); + sprite.scale.set(2, 4); + // causes fail + // sprite.angle = 180; final cam = FlxG.camera; cam.scroll.set(100, 100); cam.zoom *= 2; - final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); - final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); - final center = FlxPoint.get(cam.viewX + (cam.viewWidth - graphicWidth) / 2, cam.viewY + (cam.viewHeight - graphicHeight) / 2); + final graphicBounds = sprite.getScreenBounds(null, cam); + final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); + final center = FlxPoint.get((cam.width - graphicBounds.width) / 2 + offset.x, (cam.height - graphicBounds.height) / 2 + offset.y); final offCenter = center.copyTo().add(1000, 1000); sprite.setPosition(offCenter.x, offCenter.y); @@ -125,6 +129,8 @@ class FlxCameraTest extends FlxTest Assert.areEqual(sprite.x, center.x); Assert.areEqual(sprite.y, center.y); + offset.put(); + graphicBounds.put(); offCenter.put(); center.put(); } @@ -136,7 +142,9 @@ class FlxCameraTest extends FlxTest final cam = FlxG.camera; cam.scroll.set(100, 100); cam.zoom *= 2; - final center = FlxPoint.get(cam.viewX + (cam.viewWidth - object.width) / 2, cam.viewY + (cam.viewHeight - object.height) / 2); + final hitbox = object.getHitbox(); + final offset = FlxPoint.get(object.x - hitbox.x, object.y - hitbox.y); + final center = FlxPoint.get(cam.scroll.x + (cam.width - hitbox.width) / 2 + offset.x, cam.scroll.y + (cam.height - hitbox.height) / 2 + offset.y); final offCenter = center.copyTo().add(1000, 1000); object.setPosition(offCenter.x, offCenter.y); @@ -159,6 +167,8 @@ class FlxCameraTest extends FlxTest Assert.areEqual(object.x, center.x); Assert.areEqual(object.y, center.y); + offset.put(); + hitbox.put(); offCenter.put(); center.put(); } diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index b24082c5c0..16c9f199b0 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -110,11 +110,15 @@ class FlxGTest extends FlxTest function testCenter() { final sprite = new FlxSprite(); - sprite.makeGraphic(10, 10); - sprite.scale.set(-2, -4); - final graphicWidth = sprite.frameWidth * Math.abs(sprite.scale.x); - final graphicHeight = sprite.frameHeight * Math.abs(sprite.scale.y); - final center = FlxPoint.get((FlxG.width - graphicWidth) / 2, (FlxG.height - graphicHeight) / 2); + sprite.makeGraphic(100, 100); + sprite.origin.set(100, 100); + sprite.offset.set(100, 100); + sprite.scale.set(2, 4); + // causes fail + // sprite.angle = 180; + final graphicBounds = sprite.getGraphicBounds(); + final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); + final center = FlxPoint.get((FlxG.width - graphicBounds.width) / 2 + offset.x, (FlxG.height - graphicBounds.height) / 2 + offset.y); final offCenter = center.copyTo().add(1000, 1000); sprite.setPosition(offCenter.x, offCenter.y); @@ -137,6 +141,8 @@ class FlxGTest extends FlxTest Assert.areEqual(sprite.x, center.x); Assert.areEqual(sprite.y, center.y); + offset.put(); + graphicBounds.put(); offCenter.put(); center.put(); } @@ -145,7 +151,9 @@ class FlxGTest extends FlxTest function testCenterHitbox() { final object = new FlxObject(0, 0, 10, 10); - final center = FlxPoint.get((FlxG.width - object.width) / 2, (FlxG.height - object.height) / 2); + final hitbox = object.getHitbox(); + final offset = FlxPoint.get(object.x - hitbox.x, object.y - hitbox.y); + final center = FlxPoint.get((FlxG.width - hitbox.width) / 2 + offset.x, (FlxG.height - hitbox.height) / 2 + offset.y); final offCenter = center.copyTo().add(1000, 1000); object.setPosition(offCenter.x, offCenter.y); @@ -168,6 +176,8 @@ class FlxGTest extends FlxTest Assert.areEqual(object.x, center.x); Assert.areEqual(object.y, center.y); + offset.put(); + hitbox.put(); offCenter.put(); center.put(); } From a593d5a84f1414b036691004ec8c747a6eb891f8 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Fri, 21 Feb 2025 22:34:02 +0400 Subject: [PATCH 3/9] test --- tests/unit/src/flixel/FlxCameraTest.hx | 3 +-- tests/unit/src/flixel/FlxGTest.hx | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 51f287025a..31b93c3367 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -99,8 +99,7 @@ class FlxCameraTest extends FlxTest sprite.origin.set(100, 100); sprite.offset.set(100, 100); sprite.scale.set(2, 4); - // causes fail - // sprite.angle = 180; + sprite.angle = 180; final cam = FlxG.camera; cam.scroll.set(100, 100); cam.zoom *= 2; diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 16c9f199b0..73213f3b5e 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -114,8 +114,7 @@ class FlxGTest extends FlxTest sprite.origin.set(100, 100); sprite.offset.set(100, 100); sprite.scale.set(2, 4); - // causes fail - // sprite.angle = 180; + sprite.angle = 180; final graphicBounds = sprite.getGraphicBounds(); final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); final center = FlxPoint.get((FlxG.width - graphicBounds.width) / 2 + offset.x, (FlxG.height - graphicBounds.height) / 2 + offset.y); From f720a2bd2a4248c4ebd1ff3920ecae7cd2328147 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Fri, 21 Feb 2025 23:04:02 +0400 Subject: [PATCH 4/9] test again --- tests/unit/src/flixel/FlxCameraTest.hx | 16 ++++++++-------- tests/unit/src/flixel/FlxGTest.hx | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 31b93c3367..f7db289b43 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -110,23 +110,23 @@ class FlxCameraTest extends FlxTest sprite.setPosition(offCenter.x, offCenter.y); cam.center(sprite, X); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, offCenter.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, offCenter.y); sprite.setPosition(offCenter.x, offCenter.y); cam.center(sprite, Y); - Assert.areEqual(sprite.x, offCenter.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, offCenter.x); + FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); cam.center(sprite, XY); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); cam.center(sprite); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, center.y); offset.put(); graphicBounds.put(); diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 73213f3b5e..2872866bf5 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -122,23 +122,23 @@ class FlxGTest extends FlxTest sprite.setPosition(offCenter.x, offCenter.y); FlxG.center(sprite, X); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, offCenter.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, offCenter.y); sprite.setPosition(offCenter.x, offCenter.y); FlxG.center(sprite, Y); - Assert.areEqual(sprite.x, offCenter.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, offCenter.x); + FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); FlxG.center(sprite, XY); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); FlxG.center(sprite); - Assert.areEqual(sprite.x, center.x); - Assert.areEqual(sprite.y, center.y); + FlxAssert.areNear(sprite.x, center.x); + FlxAssert.areNear(sprite.y, center.y); offset.put(); graphicBounds.put(); From 5b474328a006be32bb5ea0f68bb8c0816b0e862a Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Wed, 9 Apr 2025 02:55:18 +0400 Subject: [PATCH 5/9] fix pixel perfect sprite centering --- flixel/FlxCamera.hx | 9 +++++++++ flixel/FlxG.hx | 6 ++++++ flixel/FlxSprite.hx | 4 ++-- tests/unit/src/flixel/FlxCameraTest.hx | 2 ++ tests/unit/src/flixel/FlxGTest.hx | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index c3eeba8c01..6d01b553b5 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1883,6 +1883,12 @@ class FlxCamera extends FlxBasic */ public function center(sprite:T, axes:FlxAxes = XY):T { + // We need to disable these flags to get accurate graphic bounds + final pixelPerfectPosition = sprite.pixelPerfectPosition; + final pixelPerfectRender = sprite.pixelPerfectRender; + sprite.pixelPerfectPosition = false; + @:bypassAccessor sprite.pixelPerfectRender = false; + final graphicBounds = sprite.getScreenBounds(null, this); if (axes.x) @@ -1897,6 +1903,9 @@ class FlxCamera extends FlxBasic sprite.y = (height - graphicBounds.height) / 2 + offset; } + // Now we set flags back to their original state + sprite.pixelPerfectPosition = pixelPerfectPosition; + @:bypassAccessor sprite.pixelPerfectRender = pixelPerfectRender; graphicBounds.put(); return sprite; } diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 443e4e0cd0..462d4e6015 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -488,6 +488,10 @@ class FlxG */ public static function center(sprite:T, axes:FlxAxes = XY):T { + // We need to disable this flag to get accurate graphic bounds + final pixelPerfectPosition = sprite.pixelPerfectPosition; + sprite.pixelPerfectPosition = false; + final graphicBounds = sprite.getGraphicBounds(); if (axes.x) @@ -502,6 +506,8 @@ class FlxG sprite.y = (FlxG.height - graphicBounds.height) / 2 + offset; } + // Now we set flag back to its original state + sprite.pixelPerfectPosition = pixelPerfectPosition; graphicBounds.put(); return sprite; } diff --git a/flixel/FlxSprite.hx b/flixel/FlxSprite.hx index 27cbb5af0c..6f032b595f 100644 --- a/flixel/FlxSprite.hx +++ b/flixel/FlxSprite.hx @@ -1368,8 +1368,8 @@ class FlxSprite extends FlxObject if (pixelPerfectPosition) newRect.floor(); _scaledOrigin.set(origin.x * scale.x, origin.y * scale.y); - newRect.x += -Std.int(camera.scroll.x * scrollFactor.x) - offset.x + origin.x - _scaledOrigin.x; - newRect.y += -Std.int(camera.scroll.y * scrollFactor.y) - offset.y + origin.y - _scaledOrigin.y; + newRect.x += -camera.scroll.x * scrollFactor.x - offset.x + origin.x - _scaledOrigin.x; + newRect.y += -camera.scroll.y * scrollFactor.y - offset.y + origin.y - _scaledOrigin.y; if (isPixelPerfectRender(camera)) newRect.floor(); newRect.setSize(frameWidth * Math.abs(scale.x), frameHeight * Math.abs(scale.y)); diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index f7db289b43..e396ab5bc4 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -100,6 +100,8 @@ class FlxCameraTest extends FlxTest sprite.offset.set(100, 100); sprite.scale.set(2, 4); sprite.angle = 180; + sprite.pixelPerfectPosition = true; + sprite.pixelPerfectRender = true; final cam = FlxG.camera; cam.scroll.set(100, 100); cam.zoom *= 2; diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 2872866bf5..a4d36d314c 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -115,6 +115,7 @@ class FlxGTest extends FlxTest sprite.offset.set(100, 100); sprite.scale.set(2, 4); sprite.angle = 180; + sprite.pixelPerfectPosition = true; final graphicBounds = sprite.getGraphicBounds(); final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); final center = FlxPoint.get((FlxG.width - graphicBounds.width) / 2 + offset.x, (FlxG.height - graphicBounds.height) / 2 + offset.y); From cbf91ce703c26b0663a107a4efe2028919b934d6 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Thu, 10 Apr 2025 05:42:26 +0400 Subject: [PATCH 6/9] name change --- flixel/FlxCamera.hx | 6 +++--- flixel/FlxG.hx | 6 +++--- tests/unit/src/flixel/FlxCameraTest.hx | 14 +++++++------- tests/unit/src/flixel/FlxGTest.hx | 14 +++++++------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 6d01b553b5..abcc4bb927 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1879,9 +1879,9 @@ class FlxCamera extends FlxBasic * @param sprite The sprite to center. * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered sprite for chaining. - * @since TBA + * @since 6.2.0 */ - public function center(sprite:T, axes:FlxAxes = XY):T + public function centerGraphic(sprite:T, axes:FlxAxes = XY):T { // We need to disable these flags to get accurate graphic bounds final pixelPerfectPosition = sprite.pixelPerfectPosition; @@ -1916,7 +1916,7 @@ class FlxCamera extends FlxBasic * @param object The object to center. * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered object for chaining. - * @since TBA + * @since 6.2.0 */ public function centerHitbox(object:T, axes:FlxAxes = XY):T { diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 462d4e6015..6f09ad9caa 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -484,9 +484,9 @@ class FlxG * @param sprite The sprite to center. * @param axes On what axes to center the sprite (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered sprite for chaining. - * @since TBA + * @since 6.2.0 */ - public static function center(sprite:T, axes:FlxAxes = XY):T + public static function centerGraphic(sprite:T, axes:FlxAxes = XY):T { // We need to disable this flag to get accurate graphic bounds final pixelPerfectPosition = sprite.pixelPerfectPosition; @@ -518,7 +518,7 @@ class FlxG * @param object The object to center. * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return Centered object for chaining. - * @since TBA + * @since 6.2.0 */ public static function centerHitbox(object:T, axes:FlxAxes = XY):T { diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index e396ab5bc4..5c78c63265 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -91,8 +91,8 @@ class FlxCameraTest extends FlxTest Assert.areEqual(defaultLerp, camera.followLerp); } - @Test - function testCenter() + @Test // #3329 + function testCenterGraphic() { final sprite = new FlxSprite(); sprite.makeGraphic(100, 100); @@ -111,22 +111,22 @@ class FlxCameraTest extends FlxTest final offCenter = center.copyTo().add(1000, 1000); sprite.setPosition(offCenter.x, offCenter.y); - cam.center(sprite, X); + cam.centerGraphic(sprite, X); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, offCenter.y); sprite.setPosition(offCenter.x, offCenter.y); - cam.center(sprite, Y); + cam.centerGraphic(sprite, Y); FlxAssert.areNear(sprite.x, offCenter.x); FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); - cam.center(sprite, XY); + cam.centerGraphic(sprite, XY); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); - cam.center(sprite); + cam.centerGraphic(sprite); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, center.y); @@ -136,7 +136,7 @@ class FlxCameraTest extends FlxTest center.put(); } - @Test + @Test // #3329 function testCenterHitbox() { final object = new FlxObject(0, 0, 10, 10); diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index a4d36d314c..0ec8ab4d9f 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -106,8 +106,8 @@ class FlxGTest extends FlxTest Assert.areEqual(480, FlxG.height); } - @Test - function testCenter() + @Test // #3329 + function testCenterGraphic() { final sprite = new FlxSprite(); sprite.makeGraphic(100, 100); @@ -122,22 +122,22 @@ class FlxGTest extends FlxTest final offCenter = center.copyTo().add(1000, 1000); sprite.setPosition(offCenter.x, offCenter.y); - FlxG.center(sprite, X); + FlxG.centerGraphic(sprite, X); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, offCenter.y); sprite.setPosition(offCenter.x, offCenter.y); - FlxG.center(sprite, Y); + FlxG.centerGraphic(sprite, Y); FlxAssert.areNear(sprite.x, offCenter.x); FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); - FlxG.center(sprite, XY); + FlxG.centerGraphic(sprite, XY); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, center.y); sprite.setPosition(offCenter.x, offCenter.y); - FlxG.center(sprite); + FlxG.centerGraphic(sprite); FlxAssert.areNear(sprite.x, center.x); FlxAssert.areNear(sprite.y, center.y); @@ -147,7 +147,7 @@ class FlxGTest extends FlxTest center.put(); } - @Test + @Test // #3329 function testCenterHitbox() { final object = new FlxObject(0, 0, 10, 10); From e3f9d55d6e88d2e8a5865a480e4453fa25905cf6 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Thu, 10 Apr 2025 05:43:24 +0400 Subject: [PATCH 7/9] revert "fix pixel perfect sprite centering" --- flixel/FlxCamera.hx | 22 ++-------------------- flixel/FlxG.hx | 19 ++----------------- 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index abcc4bb927..40a9ce2c2f 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1883,12 +1883,6 @@ class FlxCamera extends FlxBasic */ public function centerGraphic(sprite:T, axes:FlxAxes = XY):T { - // We need to disable these flags to get accurate graphic bounds - final pixelPerfectPosition = sprite.pixelPerfectPosition; - final pixelPerfectRender = sprite.pixelPerfectRender; - sprite.pixelPerfectPosition = false; - @:bypassAccessor sprite.pixelPerfectRender = false; - final graphicBounds = sprite.getScreenBounds(null, this); if (axes.x) @@ -1903,9 +1897,6 @@ class FlxCamera extends FlxBasic sprite.y = (height - graphicBounds.height) / 2 + offset; } - // Now we set flags back to their original state - sprite.pixelPerfectPosition = pixelPerfectPosition; - @:bypassAccessor sprite.pixelPerfectRender = pixelPerfectRender; graphicBounds.put(); return sprite; } @@ -1920,21 +1911,12 @@ class FlxCamera extends FlxBasic */ public function centerHitbox(object:T, axes:FlxAxes = XY):T { - final hitbox = object.getHitbox(); - if (axes.x) - { - final offset = object.x - hitbox.x; - object.x = scroll.x + (width - hitbox.width) / 2 + offset; - } + object.x = scroll.x + (width - object.width) / 2; if (axes.y) - { - final offset = object.y - hitbox.y; - object.y = scroll.y + (height - hitbox.height) / 2 + offset; - } + object.y = scroll.y + (height - object.height) / 2; - hitbox.put(); return object; } diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 6f09ad9caa..1b3bafd946 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -488,10 +488,6 @@ class FlxG */ public static function centerGraphic(sprite:T, axes:FlxAxes = XY):T { - // We need to disable this flag to get accurate graphic bounds - final pixelPerfectPosition = sprite.pixelPerfectPosition; - sprite.pixelPerfectPosition = false; - final graphicBounds = sprite.getGraphicBounds(); if (axes.x) @@ -506,8 +502,6 @@ class FlxG sprite.y = (FlxG.height - graphicBounds.height) / 2 + offset; } - // Now we set flag back to its original state - sprite.pixelPerfectPosition = pixelPerfectPosition; graphicBounds.put(); return sprite; } @@ -522,21 +516,12 @@ class FlxG */ public static function centerHitbox(object:T, axes:FlxAxes = XY):T { - final hitbox = object.getHitbox(); - if (axes.x) - { - final offset = object.x - hitbox.x; - object.x = (FlxG.width - hitbox.width) / 2 + offset; - } + object.x = (FlxG.width - object.width) / 2; if (axes.y) - { - final offset = object.y - hitbox.y; - object.y = (FlxG.height - hitbox.height) / 2 + offset; - } + object.y = (FlxG.height - object.height) / 2; - hitbox.put(); return object; } From 76282847ccae3505dc592bb576ecf11ba1556472 Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Thu, 10 Apr 2025 05:44:59 +0400 Subject: [PATCH 8/9] hardcode unit tests --- tests/unit/src/flixel/FlxCameraTest.hx | 93 ++++++++++++-------------- tests/unit/src/flixel/FlxGTest.hx | 82 ++++++++++------------- tests/unit/src/flixel/FlxObjectTest.hx | 31 --------- 3 files changed, 81 insertions(+), 125 deletions(-) diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 5c78c63265..3216aba10a 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -94,84 +94,79 @@ class FlxCameraTest extends FlxTest @Test // #3329 function testCenterGraphic() { + final cam = FlxG.camera; + cam.scroll.set(100, 100); + cam.zoom *= 2; + + Assert.areEqual(cam.width, 640); + Assert.areEqual(cam.height, 480); + final sprite = new FlxSprite(); - sprite.makeGraphic(100, 100); - sprite.origin.set(100, 100); - sprite.offset.set(100, 100); + sprite.makeGraphic(10, 10); + sprite.scrollFactor.set(2, 2); + sprite.origin.set(10, 10); + sprite.offset.set(10, 10); sprite.scale.set(2, 4); sprite.angle = 180; sprite.pixelPerfectPosition = true; sprite.pixelPerfectRender = true; - final cam = FlxG.camera; - cam.scroll.set(100, 100); - cam.zoom *= 2; - final graphicBounds = sprite.getScreenBounds(null, cam); - final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); - final center = FlxPoint.get((cam.width - graphicBounds.width) / 2 + offset.x, (cam.height - graphicBounds.height) / 2 + offset.y); - final offCenter = center.copyTo().add(1000, 1000); - sprite.setPosition(offCenter.x, offCenter.y); + function assertCenterGraphic(sprite, expectedX, expectedY) + { + FlxAssert.areNear(sprite.x, expectedX); + FlxAssert.areNear(sprite.y, expectedY); + } + + sprite.setPosition(0, 0); cam.centerGraphic(sprite, X); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, offCenter.y); + assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 0); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(0, 0); cam.centerGraphic(sprite, Y); - FlxAssert.areNear(sprite.x, offCenter.x); - FlxAssert.areNear(sprite.y, center.y); + assertCenterGraphic(sprite, 0, 100 + 240 - 20 - (-110 + 10)); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(0, 0); cam.centerGraphic(sprite, XY); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, center.y); + assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 100 + 240 - 20 - (-110 + 10)); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(1640, 1480); cam.centerGraphic(sprite); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, center.y); - - offset.put(); - graphicBounds.put(); - offCenter.put(); - center.put(); + assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 100 + 240 - 20 - (-110 + 10)); } @Test // #3329 function testCenterHitbox() { - final object = new FlxObject(0, 0, 10, 10); final cam = FlxG.camera; cam.scroll.set(100, 100); cam.zoom *= 2; - final hitbox = object.getHitbox(); - final offset = FlxPoint.get(object.x - hitbox.x, object.y - hitbox.y); - final center = FlxPoint.get(cam.scroll.x + (cam.width - hitbox.width) / 2 + offset.x, cam.scroll.y + (cam.height - hitbox.height) / 2 + offset.y); - final offCenter = center.copyTo().add(1000, 1000); - object.setPosition(offCenter.x, offCenter.y); + Assert.areEqual(cam.width, 640); + Assert.areEqual(cam.height, 480); + + final object = new FlxObject(0, 0, 10, 10); + + function assertCenterHitbox(object, expectedX, expectedY) + { + Assert.areEqual(object.x, expectedX); + Assert.areEqual(object.y, expectedY); + } + + object.setPosition(0, 0); cam.centerHitbox(object, X); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, offCenter.y); + assertCenterHitbox(object, 100 + 320 - 5, 0); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(0, 0); cam.centerHitbox(object, Y); - Assert.areEqual(object.x, offCenter.x); - Assert.areEqual(object.y, center.y); + assertCenterHitbox(object, 0, 100 + 240 - 5); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(0, 0); cam.centerHitbox(object, XY); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, center.y); + assertCenterHitbox(object, 100 + 320 - 5, 100 + 240 - 5); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(1640, 1480); cam.centerHitbox(object); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, center.y); - - offset.put(); - hitbox.put(); - offCenter.put(); - center.put(); + assertCenterHitbox(object, 100 + 320 - 5, 100 + 240 - 5); } @Test diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 0ec8ab4d9f..55fa341e96 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -109,76 +109,68 @@ class FlxGTest extends FlxTest @Test // #3329 function testCenterGraphic() { + Assert.areEqual(FlxG.width, 640); + Assert.areEqual(FlxG.height, 480); + final sprite = new FlxSprite(); - sprite.makeGraphic(100, 100); - sprite.origin.set(100, 100); - sprite.offset.set(100, 100); + sprite.makeGraphic(10, 10); + sprite.origin.set(10, 10); + sprite.offset.set(10, 10); sprite.scale.set(2, 4); sprite.angle = 180; sprite.pixelPerfectPosition = true; - final graphicBounds = sprite.getGraphicBounds(); - final offset = FlxPoint.get(sprite.x - graphicBounds.x, sprite.y - graphicBounds.y); - final center = FlxPoint.get((FlxG.width - graphicBounds.width) / 2 + offset.x, (FlxG.height - graphicBounds.height) / 2 + offset.y); - final offCenter = center.copyTo().add(1000, 1000); - sprite.setPosition(offCenter.x, offCenter.y); + function assertCenterGraphic(sprite, expectedX, expectedY) + { + FlxAssert.areNear(sprite.x, expectedX); + FlxAssert.areNear(sprite.y, expectedY); + } + + sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, X); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, offCenter.y); + assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 0); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, Y); - FlxAssert.areNear(sprite.x, offCenter.x); - FlxAssert.areNear(sprite.y, center.y); + assertCenterGraphic(sprite, 0, 240 - 20 - (-10 + 10)); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, XY); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, center.y); + assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); - sprite.setPosition(offCenter.x, offCenter.y); + sprite.setPosition(1640, 1480); FlxG.centerGraphic(sprite); - FlxAssert.areNear(sprite.x, center.x); - FlxAssert.areNear(sprite.y, center.y); - - offset.put(); - graphicBounds.put(); - offCenter.put(); - center.put(); + assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); } @Test // #3329 function testCenterHitbox() { + Assert.areEqual(FlxG.width, 640); + Assert.areEqual(FlxG.height, 480); + final object = new FlxObject(0, 0, 10, 10); - final hitbox = object.getHitbox(); - final offset = FlxPoint.get(object.x - hitbox.x, object.y - hitbox.y); - final center = FlxPoint.get((FlxG.width - hitbox.width) / 2 + offset.x, (FlxG.height - hitbox.height) / 2 + offset.y); - final offCenter = center.copyTo().add(1000, 1000); - object.setPosition(offCenter.x, offCenter.y); + function assertCenterHitbox(object, expectedX, expectedY) + { + Assert.areEqual(object.x, expectedX); + Assert.areEqual(object.y, expectedY); + } + + object.setPosition(0, 0); FlxG.centerHitbox(object, X); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, offCenter.y); + assertCenterHitbox(object, 320 - 5, 0); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(0, 0); FlxG.centerHitbox(object, Y); - Assert.areEqual(object.x, offCenter.x); - Assert.areEqual(object.y, center.y); + assertCenterHitbox(object, 0, 240 - 5); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(0, 0); FlxG.centerHitbox(object, XY); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, center.y); + assertCenterHitbox(object, 320 - 5, 240 - 5); - object.setPosition(offCenter.x, offCenter.y); + object.setPosition(1640, 1480); FlxG.centerHitbox(object); - Assert.areEqual(object.x, center.x); - Assert.areEqual(object.y, center.y); - - offset.put(); - hitbox.put(); - offCenter.put(); - center.put(); + assertCenterHitbox(object, 320 - 5, 240 - 5); } } diff --git a/tests/unit/src/flixel/FlxObjectTest.hx b/tests/unit/src/flixel/FlxObjectTest.hx index 99e9987126..ac830f4420 100644 --- a/tests/unit/src/flixel/FlxObjectTest.hx +++ b/tests/unit/src/flixel/FlxObjectTest.hx @@ -340,37 +340,6 @@ class FlxObjectTest extends FlxTest assertNotOnScreen(0, FlxG.height); } - @Test - @:haxe.warning("-WDeprecated") // TODO: remove this test? - function testScreenCenter() - { - var center = FlxPoint.get((FlxG.width - object1.width) / 2, (FlxG.height - object1.height) / 2); - var offCenter = center.copyTo().add(1000, 1000); - - object1.setPosition(offCenter.x, offCenter.y); - object1.screenCenter(X); - Assert.areEqual(object1.x, center.x); - Assert.areEqual(object1.y, offCenter.y); - - object1.setPosition(offCenter.x, offCenter.y); - object1.screenCenter(Y); - Assert.areEqual(object1.x, offCenter.x); - Assert.areEqual(object1.y, center.y); - - object1.setPosition(offCenter.x, offCenter.y); - object1.screenCenter(XY); - Assert.areEqual(object1.x, center.x); - Assert.areEqual(object1.y, center.y); - - object1.setPosition(offCenter.x, offCenter.y); - object1.screenCenter(); - Assert.areEqual(object1.x, center.x); - Assert.areEqual(object1.y, center.y); - - offCenter.put(); - center.put(); - } - @Test function testgetRotatedBounds() { From 6caea686c6762ddd9feb2703051d9f6a47061c4d Mon Sep 17 00:00:00 2001 From: richTrash21 <87835336+richTrash21@users.noreply.github.com> Date: Wed, 16 Jul 2025 13:33:37 +0400 Subject: [PATCH 9/9] add "accurate" methods --- flixel/FlxCamera.hx | 2 +- flixel/FlxG.hx | 2 +- flixel/FlxObject.hx | 22 +++++++++---- flixel/FlxSprite.hx | 45 +++++++++++++++++++------- tests/unit/src/flixel/FlxCameraTest.hx | 39 ++++++++++------------ tests/unit/src/flixel/FlxGTest.hx | 35 +++++++++----------- 6 files changed, 83 insertions(+), 62 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 40a9ce2c2f..a978e02187 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1883,7 +1883,7 @@ class FlxCamera extends FlxBasic */ public function centerGraphic(sprite:T, axes:FlxAxes = XY):T { - final graphicBounds = sprite.getScreenBounds(null, this); + final graphicBounds = sprite.getAccurateScreenBounds(null, this); if (axes.x) { diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 1b3bafd946..81a9aea02c 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -488,7 +488,7 @@ class FlxG */ public static function centerGraphic(sprite:T, axes:FlxAxes = XY):T { - final graphicBounds = sprite.getGraphicBounds(); + final graphicBounds = sprite.getAccurateGraphicBounds(); if (axes.x) { diff --git a/flixel/FlxObject.hx b/flixel/FlxObject.hx index a88e33ebc6..c484d2ba8f 100644 --- a/flixel/FlxObject.hx +++ b/flixel/FlxObject.hx @@ -1031,7 +1031,7 @@ class FlxObject extends FlxBasic { return (x + width > FlxG.worldBounds.x) && (x < FlxG.worldBounds.right) && (y + height > FlxG.worldBounds.y) && (y < FlxG.worldBounds.bottom); } - + /** * Returns the screen position of this object. * @@ -1040,20 +1040,30 @@ class FlxObject extends FlxBasic * @return The screen position of this object. */ public function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + return getScreenPositionHelper(result, camera, true); + } + + public function getAccurateScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + return getScreenPositionHelper(result, camera, false); + } + + public function getScreenPositionHelper(result:FlxPoint, camera:FlxCamera, honorPixelPerfect:Bool):FlxPoint { if (result == null) result = FlxPoint.get(); - + if (camera == null) camera = getDefaultCamera(); - + result.set(x, y); - if (pixelPerfectPosition) + if (honorPixelPerfect && pixelPerfectPosition) result.floor(); - + return result.subtract(camera.scroll.x * scrollFactor.x, camera.scroll.y * scrollFactor.y); } - + /** * Returns the world position of this object. * diff --git a/flixel/FlxSprite.hx b/flixel/FlxSprite.hx index 6f032b595f..f029395d7d 100644 --- a/flixel/FlxSprite.hx +++ b/flixel/FlxSprite.hx @@ -1269,23 +1269,31 @@ class FlxSprite extends FlxObject * @since 5.9.0 */ public function getGraphicBounds(?rect:FlxRect):FlxRect + { + return getGraphicBoundsHelper(rect, true); + } + + public function getAccurateGraphicBounds(?rect:FlxRect):FlxRect + { + return getGraphicBoundsHelper(rect, false); + } + + public function getGraphicBoundsHelper(rect:FlxRect, honorPixelPerfect:Bool):FlxRect { if (rect == null) rect = FlxRect.get(); rect.set(x, y); - if (pixelPerfectPosition) + if (honorPixelPerfect && pixelPerfectPosition) rect.floor(); - _scaledOrigin.set(origin.x * scale.x, origin.y * scale.y); + final absoluteScale = _point.set(Math.abs(scale.x), Math.abs(scale.y)); + _scaledOrigin.set(origin.x * absoluteScale.x, origin.y * absoluteScale.y); rect.x += origin.x - offset.x - _scaledOrigin.x; rect.y += origin.y - offset.y - _scaledOrigin.y; - rect.setSize(frameWidth * scale.x, frameHeight * scale.y); + rect.setSize(frameWidth * absoluteScale.x, frameHeight * absoluteScale.y); - if (angle % 360 != 0) - rect.getRotatedBounds(angle, _scaledOrigin, rect); - - return rect; + return rect.getRotatedBounds(angle, _scaledOrigin, rect); } /** @@ -1339,7 +1347,7 @@ class FlxSprite extends FlxObject * @return A globally aligned `FlxRect` that fully contains the input object's width and height. * @since 4.11.0 */ - override function getRotatedBounds(?newRect:FlxRect) + override public function getRotatedBounds(?newRect:FlxRect):FlxRect { if (newRect == null) newRect = FlxRect.get(); @@ -1357,6 +1365,16 @@ class FlxSprite extends FlxObject * @since 4.11.0 */ public function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect + { + return getScreenBoundsHelper(newRect, camera, true); + } + + public function getAccurateScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect + { + return getScreenBoundsHelper(newRect, camera, false); + } + + function getScreenBoundsHelper(newRect:FlxRect, camera:FlxCamera, honorPixelPerfect:Bool):FlxRect { if (newRect == null) newRect = FlxRect.get(); @@ -1365,14 +1383,17 @@ class FlxSprite extends FlxObject camera = getDefaultCamera(); newRect.setPosition(x, y); - if (pixelPerfectPosition) + if (honorPixelPerfect && pixelPerfectPosition) newRect.floor(); - _scaledOrigin.set(origin.x * scale.x, origin.y * scale.y); + + final absoluteScale = _point.set(Math.abs(scale.x), Math.abs(scale.y)); + _scaledOrigin.set(origin.x * absoluteScale.x, origin.y * absoluteScale.y); newRect.x += -camera.scroll.x * scrollFactor.x - offset.x + origin.x - _scaledOrigin.x; newRect.y += -camera.scroll.y * scrollFactor.y - offset.y + origin.y - _scaledOrigin.y; - if (isPixelPerfectRender(camera)) + if (honorPixelPerfect && isPixelPerfectRender(camera)) newRect.floor(); - newRect.setSize(frameWidth * Math.abs(scale.x), frameHeight * Math.abs(scale.y)); + + newRect.setSize(frameWidth * absoluteScale.x, frameHeight * absoluteScale.y); return newRect.getRotatedBounds(angle, _scaledOrigin, newRect); } diff --git a/tests/unit/src/flixel/FlxCameraTest.hx b/tests/unit/src/flixel/FlxCameraTest.hx index 3216aba10a..7fee0290b0 100644 --- a/tests/unit/src/flixel/FlxCameraTest.hx +++ b/tests/unit/src/flixel/FlxCameraTest.hx @@ -2,6 +2,7 @@ package flixel; import flixel.math.FlxPoint; import flixel.util.FlxColor; +import haxe.PosInfos; import massive.munit.Assert; @:access(flixel.system.frontEnds.CameraFrontEnd) @@ -95,7 +96,7 @@ class FlxCameraTest extends FlxTest function testCenterGraphic() { final cam = FlxG.camera; - cam.scroll.set(100, 100); + cam.scroll.set(100.5, 100.5); cam.zoom *= 2; Assert.areEqual(cam.width, 640); @@ -111,34 +112,28 @@ class FlxCameraTest extends FlxTest sprite.pixelPerfectPosition = true; sprite.pixelPerfectRender = true; - function assertCenterGraphic(sprite, expectedX, expectedY) - { - FlxAssert.areNear(sprite.x, expectedX); - FlxAssert.areNear(sprite.y, expectedY); - } - sprite.setPosition(0, 0); cam.centerGraphic(sprite, X); - assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 0); + assertCenter(sprite, 100.5 + 320 - 10 - (-110.5 + 10), 0); sprite.setPosition(0, 0); cam.centerGraphic(sprite, Y); - assertCenterGraphic(sprite, 0, 100 + 240 - 20 - (-110 + 10)); + assertCenter(sprite, 0, 100.5 + 240 - 20 - (-110.5 + 10)); sprite.setPosition(0, 0); cam.centerGraphic(sprite, XY); - assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 100 + 240 - 20 - (-110 + 10)); + assertCenter(sprite, 100.5 + 320 - 10 - (-110.5 + 10), 100.5 + 240 - 20 - (-110.5 + 10)); sprite.setPosition(1640, 1480); cam.centerGraphic(sprite); - assertCenterGraphic(sprite, 100 + 320 - 10 - (-110 + 10), 100 + 240 - 20 - (-110 + 10)); + assertCenter(sprite, 100.5 + 320 - 10 - (-110.5 + 10), 100.5 + 240 - 20 - (-110.5 + 10)); } @Test // #3329 function testCenterHitbox() { final cam = FlxG.camera; - cam.scroll.set(100, 100); + cam.scroll.set(100.5, 100.5); cam.zoom *= 2; Assert.areEqual(cam.width, 640); @@ -146,27 +141,27 @@ class FlxCameraTest extends FlxTest final object = new FlxObject(0, 0, 10, 10); - function assertCenterHitbox(object, expectedX, expectedY) - { - Assert.areEqual(object.x, expectedX); - Assert.areEqual(object.y, expectedY); - } - object.setPosition(0, 0); cam.centerHitbox(object, X); - assertCenterHitbox(object, 100 + 320 - 5, 0); + assertCenter(object, 100.5 + 320 - 5, 0); object.setPosition(0, 0); cam.centerHitbox(object, Y); - assertCenterHitbox(object, 0, 100 + 240 - 5); + assertCenter(object, 0, 100.5 + 240 - 5); object.setPosition(0, 0); cam.centerHitbox(object, XY); - assertCenterHitbox(object, 100 + 320 - 5, 100 + 240 - 5); + assertCenter(object, 100.5 + 320 - 5, 100.5 + 240 - 5); object.setPosition(1640, 1480); cam.centerHitbox(object); - assertCenterHitbox(object, 100 + 320 - 5, 100 + 240 - 5); + assertCenter(object, 100.5 + 320 - 5, 100.5 + 240 - 5); + } + + function assertCenter(object:FlxObject, expectedX:Float, expectedY:Float, ?info:PosInfos) + { + FlxAssert.areNear(object.x, expectedX, info); + FlxAssert.areNear(object.y, expectedY, info); } @Test diff --git a/tests/unit/src/flixel/FlxGTest.hx b/tests/unit/src/flixel/FlxGTest.hx index 55fa341e96..1090a4f77d 100644 --- a/tests/unit/src/flixel/FlxGTest.hx +++ b/tests/unit/src/flixel/FlxGTest.hx @@ -1,6 +1,7 @@ package flixel; import flixel.math.FlxPoint; +import haxe.PosInfos; import massive.munit.Assert; @:access(flixel.FlxG) @@ -120,27 +121,21 @@ class FlxGTest extends FlxTest sprite.angle = 180; sprite.pixelPerfectPosition = true; - function assertCenterGraphic(sprite, expectedX, expectedY) - { - FlxAssert.areNear(sprite.x, expectedX); - FlxAssert.areNear(sprite.y, expectedY); - } - sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, X); - assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 0); + assertCenter(sprite, 320 - 10 - (-10 + 10), 0); sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, Y); - assertCenterGraphic(sprite, 0, 240 - 20 - (-10 + 10)); + assertCenter(sprite, 0, 240 - 20 - (-10 + 10)); sprite.setPosition(0, 0); FlxG.centerGraphic(sprite, XY); - assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); + assertCenter(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); sprite.setPosition(1640, 1480); FlxG.centerGraphic(sprite); - assertCenterGraphic(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); + assertCenter(sprite, 320 - 10 - (-10 + 10), 240 - 20 - (-10 + 10)); } @Test // #3329 @@ -151,26 +146,26 @@ class FlxGTest extends FlxTest final object = new FlxObject(0, 0, 10, 10); - function assertCenterHitbox(object, expectedX, expectedY) - { - Assert.areEqual(object.x, expectedX); - Assert.areEqual(object.y, expectedY); - } - object.setPosition(0, 0); FlxG.centerHitbox(object, X); - assertCenterHitbox(object, 320 - 5, 0); + assertCenter(object, 320 - 5, 0); object.setPosition(0, 0); FlxG.centerHitbox(object, Y); - assertCenterHitbox(object, 0, 240 - 5); + assertCenter(object, 0, 240 - 5); object.setPosition(0, 0); FlxG.centerHitbox(object, XY); - assertCenterHitbox(object, 320 - 5, 240 - 5); + assertCenter(object, 320 - 5, 240 - 5); object.setPosition(1640, 1480); FlxG.centerHitbox(object); - assertCenterHitbox(object, 320 - 5, 240 - 5); + assertCenter(object, 320 - 5, 240 - 5); + } + + function assertCenter(object:FlxObject, expectedX:Float, expectedY:Float, ?info:PosInfos) + { + FlxAssert.areNear(object.x, expectedX, info); + FlxAssert.areNear(object.y, expectedY, info); } }