ElapsedTime calculation mess

Hi,
I am trying to link the animation speed of a series of rotating objects (placed at 70 px from each other) to the elapsed time, but I’m having a very weird problem:
I have my listener:

addEventListener(Event.ENTER_FRAME, update);

and my function

private function update(event: Event):Void {
	var currentTime = Lib.getTimer ();
	var deltaTime: Float = (currentTime - previousTime) / 1000;
	previousTime = currentTime;
	
	trace(deltaTime);
	
	for (sym in symbols) {
		sym.rotation += deltaTime/*0.033*/ * 60 * symbols.indexOf(sym);
	}
}

The trace shows correctly the delta time (around 0.02 and 0.03) at each ENTER_FRAME.
If I use a fixed value (as above, the commented 0.033) I see the object rotating correctly.
If I use the calculated deltaTime I see all the objects on the same position at the top left, all overlapping and fixed, not rotating!
What’s happening?! :frowning:

you can try to round the delta (in this case 3rd decimal)

var currentTime = haxe.Timer.stamp();
var deltaTime: Float = Std.int((currentTime - previousTime) * 1000) / 1000; //milliseconds difference

I was going to take some stabs in the dark, but then I realized what it almost certainly is. Here’s the thought process I usually go through to solve this sort of problem; I suggest trying each step for yourself.

The process would start with this:

trace(symbols[0].rotation);

Hmm… that’s odd. Where did that come from?


Well, there are a few unknown values that contribute to symbols[0].rotation. For instance, symbols[0].rotation itself contributes thanks to the += operator. If the rotation was already messed up, it would stay that way.

Same with indexOf(); if it returned something crazy, that would have been passed on. (Though the worst thing indexOf() can return is -1.)

Then there’s deltaTime, and it turns out that commenting deltaTime fixes the problem.


But how would deltaTime cause the error? All the values are around 0.02-0.03… right?

(If you’re using Flash, compile in debug mode and then check this file for the full log. If you’re targeting Neko or C++, quickly close the app and scroll up.)

1 Like

Rounding the delta did the trick! Now it works, but why?

@player_03: I am exploring your answer, I already recompiled using Flash, and one detail has changed: images now are in the correct position (not overlapping), but they do not rotate (without the 3 decimals trick). When I find something else I will immediately report, anyway this looks a lot like a bug (Haxe or OpenFl), because in any other language I never had the need of rounding Numbers/Floats/Doubles to avoid this kind of behaviour.

I see from your other thread that you’ve figured out what the problem is.

But just to be clear, Math.round() is not the correct solution. The correct solution is to initialize previousTime.

I have done some more testing, and I have found the problem:

@player_03: you’re right, previousTime has not been initialized, and doing the angle calculation with a NaN messed up the rotation, that was set to NaN and stayed like that from the beginning, from the first assignment on.

This is funny because I few minutes ago I opened a new discussion about initializations here!

I am sorry I have doubted about Haxe correctness, my fault.
Thank you all for you help!

Now I am wondering why the 3 decimals trick was working: maybe the Std.int casting set a default value to the first NaN, so fixing all the following steps, I will investigate).
EDIT: yes, Std.int(NaN) returns 0 … :dizzy_face:

I assumed you started that thread because you figured this issue out… If I realized you were still working on it, I’d have let you finish.

That sounds about right. Just don’t rely on Std.int() (or Math.round(), for that matter) doing so. I’m pretty sure it’s platform-dependent.

1 - Well, I was doing tests and reading posts in a rush, I didn’t realize what the real problem was yet, I just noticed that the initial value of framesNum (a new variable introduced to calculate the average frame duration with currentTime / framesNum was initially set to NaN) and wanted to immediately share my thoughts with you in a specific thread. I didn’t immediately related this issue to previousTime, I did later by reading your reply even if initially I was like "no, it can’t be previousTime!.

2 - no problem, I absolutely won’t rely on Std.int() or Math.round() for initializations, it would be nonsense and wrong, in this situation it only messed things up making finding the problem tricky :pensive:
@yupswing well, not blaming at you, don’t worry :wink:

yeah sorry for that…

since I haven’t seen your previoustime declaration I didn’t know it was not initialised and I was assuming was 0.

I almost always init a variable when I declare it so I was not thinking about that.

@player_03 way of thinking is anyway the right way to face these kind of problems. Mine was an empiric one. Silly me :wink:

No problem, I do it “almost” always too, but I have now found that it is always necessary.
In the past I was used to receiving int values from the app-services, that later were divided by 100 to obtain the correct currency value. Later the service has been changed, and clients had to be modified to handle real values: at that point a lot of problem came out, because part of the code was using auto-initialized int values, and simply changing them from int to Number was not enough.
I have the bad habit to give the auto-init for granted, this is why I didn’t write previousTime declaration, sorry :flushed:

1 Like