I've been playing around with this problem all evening and I am completely stuck how to solve this. Jim's post was very handy as a reference:
https://forum.orx-project.org/discussion/6412#Comment_6428
Anyway here is my issue:
Say I have three animations:
HeroIdle
1 x frame
HeroJumpOver
20 x frames
HeroLanded
1 x frame
AnimLinks are: HeroIdle -> HeroJumpOver -> HeroLanded
So to have him jump over a gap, I would only need a:
orxObject_SetTargetAnim(heroObject, "HeroLanded");
So far so good. But if the gap is long, I want to slow down the animation or speed it up if the gap is short:
orxObject_SetAnimFrequency(heroObject, 0.9f);
And using SetAnimFrequency works great. But the problem is, I set the target as "HeroLanded", how can I possibly know how many frames there are between "HeroIdle" and "HeroLanded"?
I would like to take that amount of frames (20) and perform a calculation for the frequency, ie:
frequency = number-of-frames / distance-steps
Then use this on:
orxObject_SetAnimFrequency(heroObject, frequency);
So to recap, how to say:
* This is my current animation.
* This is my target animation.
* How many frames will play in total?
Thanks guys, this has me totally stumped.
Comments
All we need to do, is read from .ini and get info about our animation frames, like how many frames are there in each animations, key durations, so that we can easily calculate the time it needs to play a certain frame, or start from a certain frame, specially if your key durations differs from frame to frame.
Too cumbersome when the animation graph is already pre-loaded into memory. I am happy to write a routine to traverse the in-memory links to trace all my animations and get frame counts, but it is at this point I am lost as to where they are.
Perhaps the root of the answer is here to get to the animationset from a particular object:
https://forum.orx-project.org/discussion/6412#Comment_6428
And then make my way though using anim links using things like orxAnimSet_GetLink to gather the info.
Think I might be answering my own question.
http://orx-project.org/orx/doc/html/group__orx_anim_set.html#ga1a4a2e45162199040c07d82b261cf261
So, I think there is no way to know which animset contains how many frames and their exact time frame for each frames. But it would have been really cool if those data were accessed or may be they are stored in some other place. Now, only iarwain can answer, where those data are stored.
So far I have come up with this and it looks promising:
The problem is, even though the linkTable parameter of the ComputeAnim method is in/out, my linkTable variable remains empty. I think this a limitation of my c++ skills. I thought I could declare an empty orxANIMSET_LINK_TABLE and the ComputeAnim would populate it.
From here I hope to traverse the link table and get properties from each anim I pull out.
I think there is a more simple solution, all you need is the distance your player would normally cross during that animation period.
For example, if you character goes 10 meters in 2 seconds (here 2 second is also the time it takes to complete a jump animation, but you wont need exact time of animation, as frequency is relative) then to cross 5 meters, you need to play that animation for 1 sec, so your animation frequency should be 2, if I am not wrong
frequency = normal_distance / current_distance_to_cross
If this is not what you want, then I am not clear enough about your problem
But the more I think about it, I really have about 12 animations, not just one, and the distance time it takes normally, is the actual frame count.
If I get totally desperate, I may have to have to "double handle" all the frame lengths as a lookup table inside my code and maintain the data in both the config and the table. So if an animation is ever rebuilt and the total frames changes, I'll have to maintain in the table. Not ideal.
Oh well... if I can't get anywhere I'll have to make a table of frame lengths and just move on for now.
Sorry, I'm a bit late on that one.
First of all, the number of frames shouldn't matter, the important metrics here are distance and time.
Secondly, in your case the time spent in the air is only the duration of your HeroJumpOver, isn't it? As you do a SetTarget as soon as you take off, and the HeroLanded should play as soon as the jump is over.
You can easily change the frequency to match the time spent in the air. If you spend X seconds in the air, the frequency should be Freq = AnimLength / X.
You can set the Frequency when getting the orxANIM_EVENT_START for HeroJumpOver and reset it to 1 when getting the orxANIM_EVENT_STOP for it. As for the length of HeroJumpOver, in the event callback, you can get the orxANIM from the payload and simply have to call orxAnim_GetLength() on it.
Now if you wanted to know the cumulated time of a few consecutive anims, your code snippet using orxAnimSet_ComputeAnim() is definitely going in the right direction.
Something like this should do the trick:
You might also want to handle the case where Target is unreachable from the current animation (failsafe) by comparing the result of the call with orxU32_UNDEFINED.
You can now do the same Frequency manipulation.
If I'm missing something, please let me know.
As a side note, in most projects, jump animations are cut in more pieces: at least JumpStart, JumpLoop, JumpLand, and sometimes more cycles depending (JumpLoop would be cut into JumpRaise/JumpFall).
In those case, when jumping, one would SetTarget(JumpStart) and have the ClearTarget flags in the link that leads to JumpStart, which means there wouldn't be any target anymore when JumpStart is reached, reverting to the regular non-contrived flow of the animset (probably going to JumpLoop and looping there forever).
Then, when about to land, we'd set target with JumpLand, using the same ClearTarget flag on the link leading to it. From there it'll default probably to go back to a Idle looping animation.
If something I just said isn't very clear, please let me know.
Either solution will do me fine... I didn't give the event triggers a single thought.
And the ComputeAnim while loop, that's brilliant, I'll go for that first as it's in the area where I do my raycasting.
Made my day. Thanks for your help too Jim. Got me thinking.
If the animID values were:
HeroIdle = 0
HeroJumpOver = 14
HeroLanded = 15
The I am getting an endless loop where the returned values are constantly 14.
So the first time, 0 and 14 are compared. 14 returned
Next loop, 14 and 15 are compared. 14 returned.
Next loop, 14 and 15 are compared. 14 returned.
...and so on...
Never makes it to 15, but the value isn't unreachable with
orxU32_UNDEFINED.
The animation links appear to be fine as the animation usually works nicely, no log warnings.
I amended ComputeAnim to take in a link table but it made no difference.
I'd really like to keep heading on this method.
In order to know which anim is next, the function needs to know how much time has passed since last call. That's why you're staying always on the same animation.
Try this modification:
I'll simply add a function orxAnimSet_GetNextAnim(orxU32 _u32SourceAnimID, orxU32 _u32TargetAnimID) for you that should do exactly what you need.
You'll have to sync orx however, sorry!
If you sync the code, you can now do:
Lemme know if you have any problem!
Ok, I'll get the latest down and upgrade my project.
I'll post back on how it goes.
That function is working now as expected. Thanks so much for including that. The routine is currently:
Now the next hurdle is that orxAnimSet_ComputeAnim is only outputting 0's. Frame length is not available, so fTotalLength results in 0.
You shouldn't be calling orxAnimSet_ComputeAnim at all!
Instead, you should be using something similar to the snippet I wrote in this post.
I'm so sorry, I totally skipped over that part of the snippet when I used it to construct my loop.
Thanks Iarwain & all. My final code is: