Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlxNestedSprite movement calculations errors #422

Open
47rooks opened this issue Feb 25, 2024 · 1 comment
Open

FlxNestedSprite movement calculations errors #422

47rooks opened this issue Feb 25, 2024 · 1 comment

Comments

@47rooks
Copy link

47rooks commented Feb 25, 2024

I was reading this code the other day and noticed a that in update, preUpdate and postUpdate are call once per level of nesting in the hierarchy of objects in a FlxNestedSprite. So the top level object calls them once, the second twice, the third three times and so on. I traced it in the attached program and it's so. This should have resulted in erroneous motion calculations when relativeVelocity is non-0. I tested that and it is also true. If you set _fns2.relativeVelocity to 10. and run the program the _fns2 sprite travels approximately twice as far relative to _fns1 as it should. If instead you make _fns3.relativeVelocity = 10 and leave _fns2 relativeVelocity = 0, the _fns3 will travel 3 times as far as it should relative to _fns1 as it should. This is consistent with multiple calls to updateMotion() at each level.

This is a simple PlayState demonstrating the issue. The lib versions involved are:

Haxe 4.3.3
flixel-addons: [3.2.1]
flixel: [5.6.2]

package;

import flixel.FlxSprite;
import flixel.FlxState;
import flixel.addons.display.FlxNestedSprite;
import flixel.tweens.FlxTween;
import flixel.tweens.misc.NumTween;
import flixel.util.FlxColor;
import haxe.Timer;

class FlxDebugNestedSprite extends FlxNestedSprite
{
	var _name:String;

	public function new(name:String)
	{
		super();
		_name = name;
	}

	override public function preUpdate(elapsed:Float):Void
	{
		// trace('Starting preUpdate ${_name}');
		super.preUpdate(elapsed);
		// trace('Ending preUpdate ${_name}');
	}

	override public function update(elapsed:Float):Void
	{
		// trace('Starting update ${_name} at ${Timer.stamp()}');
		super.update(elapsed);
		// trace('Ending update ${_name} at ${Timer.stamp()}');
	}

	override public function postUpdate(elapsed:Float):Void
	{
		// trace('Starting postUpdate ${_name}');
		super.postUpdate(elapsed);
		// trace('Ending postUpdate ${_name}');
	}

	override function updateMotion(elapsed:Float):Void
	{
		// trace('Starting updateMotion ${_name}');
		super.updateMotion(elapsed);
		// trace('Ending updateMotion ${_name}');
	}
}

class PlayState extends FlxState
{
	var _fns1:FlxDebugNestedSprite;
	var _fns2:FlxDebugNestedSprite;
	var _fns3:FlxDebugNestedSprite;
	var _fns4:FlxDebugNestedSprite;

	override public function create()
	{
		super.create();

		_fns1 = new FlxDebugNestedSprite('fns1');
		_fns1.makeGraphic(100, 100, FlxColor.WHITE);
		_fns1.setPosition(0, 100);

		_fns2 = new FlxDebugNestedSprite('fns2');
		_fns2.makeGraphic(40, 40, FlxColor.BLUE);
		_fns2.relativeX = _fns2.relativeY = 50;

		_fns3 = new FlxDebugNestedSprite('fns3');
		_fns3.makeGraphic(10, 10, FlxColor.RED);
		_fns3.relativeX = 30;

		_fns4 = new FlxDebugNestedSprite('fns4');
		_fns4.makeGraphic(10, 10, FlxColor.RED);
		_fns4.relativeY = 30;

		_fns2.add(_fns3);
		_fns2.add(_fns4);
		_fns1.add(_fns2);

		add(_fns1);

		// Various motion tests

		// There is something odd with tweening which results in _fns3 and _fns4 being out of position.
		// FlxTween.tween(_fns1, {x: 600}, 1.0, {type: PINGPONG});

		// Basic white block speed
		_fns1.velocity.x = 200;

		// Relative speed tests. Uncomment _fns2 for see the example with doubled up relative distance.
		// With 10 px/sec relative to _fns1 the final displacement change in x should be about 30 pixels
		// but it is about 60.
		_fns2.relativeVelocity.x = 10;

		// Relative speed tests. Uncomment _fns3 for see the example with tripled up relative distance.
		// With 10 px/sec relative to _fns1 the final displacement change in x should be about 30 pixels
		// but it is about 90.
		// _fns3.relativeVelocity.x = 10;
	}

	override public function update(elapsed:Float)
	{
		super.update(elapsed);

		// Travelling about 200 pixels per second this gives about 3 seconds elapsed between sides
		// of the game window.
		if (_fns1.x <= 0 || _fns1.x > 600)
		{
			_fns1.velocity.x *= -1.0;
			_fns2.relativeVelocity.x *= -1.0;
			_fns3.relativeVelocity.x *= -1.0;

			// Diff the values in consecutive prints of this debug.
			trace('${Timer.stamp()}:_fns1.x=${_fns1.x} and _fns2.x=${_fns2.x} and _fns3.x=${_fns3.x}');
		}
	}
}
@47rooks
Copy link
Author

47rooks commented Feb 25, 2024

Forgot to mention that I believe this should also apply where relative acceleration is non0. I haven't tested it but the above code should be easy to modify to test that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant