Skip to content
Open
44 changes: 44 additions & 0 deletions flixel/FlxCamera.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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<T:FlxSprite>(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<T:FlxObject>(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`.
Expand Down
47 changes: 46 additions & 1 deletion flixel/FlxG.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<T:FlxSprite>(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<T:FlxObject>(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.
Expand Down
15 changes: 5 additions & 10 deletions flixel/FlxObject.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
75 changes: 74 additions & 1 deletion tests/unit/src/flixel/FlxCameraTest.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package flixel;

import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import massive.munit.Assert;

Expand Down Expand Up @@ -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()
{
Expand Down
67 changes: 67 additions & 0 deletions tests/unit/src/flixel/FlxGTest.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package flixel;

import flixel.math.FlxPoint;
import massive.munit.Assert;

@:access(flixel.FlxG)
Expand Down Expand Up @@ -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();
}
}
9 changes: 5 additions & 4 deletions tests/unit/src/flixel/FlxObjectTest.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -369,7 +370,7 @@ class FlxObjectTest extends FlxTest
offCenter.put();
center.put();
}

@Test
function testgetRotatedBounds()
{
Expand Down
Loading