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?!
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.)
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 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 …
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 @yupswing well, not blaming at you, don’t worry
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