Hi,
so I'm here with another question
First some background.
As we are making isometric we need a lot of animation for different direction (8 directions in total). Some soldier animations for instances are moving non-lineary between frames, that is there isn't constant speed of movement. So in a previous engine I was tracking actual animation frame and then move the soldier by the particular value. All our animation are data driven, so for each animation we have a JSON file which described the among other items also the movement distance for the given frame (We do this to avoid feet sliding problem in the walk animation).
edit: I've seen sausage's tutorial
http://orx-project.org/wiki/en/orx/tutorials/community/sausage/realistic_walk_movement and that is one option. But want to hear another opinions.
Now as I see orx isn't using frames in its API. All API I've used so far has some frame support. But I think I could make some wrapper class around the animation and compute the current frame from the time. Is the orxAnim_GetLength() returning the total animation time? When are the animation updated? I'm asking because my movement code need to be executed after the animation update code has been ran. Is there some event which is raised when animation frame changes? Or could I update animation manually from the code? I see there is a function orxAnim_Update() but looking through the tutorial, it isn't called anywhere so I'm assuming it is called somewhere automatically.
Another feature I was using was ping-pong looping (that is when animation is at last frame, it goes back to the first frame and so on) of the anination. I haven't found any option for setting the looping type. I could workaround to duplicate the frames for the ping-pong animation.
Also is there some counter of how many animation loops has been played already?
Also we need some functionality for starting the animation from given frame. That is because if we're playing walk-east animation and the next frame we change the walk animation to turn-nort-east animation and we need to start this animation from the exactly same frame so the animations doesn't look weird. I think using orxAnimPointer_SetTime() I could achieve this?
I've searched the forum and found some interesting topics
https://forum.orx-project.org/discussion/6604 and
https://forum.orx-project.org/discussion/6412 . Both are more than a year old so I'm curious if something has changed.
Thank You
Comments
I don't think there is a ping-pong loop, but you can use a regular loop and specify your frame in order and then descending order:
For this, you could hold a variable and increment it for every orxANIM_EVENT_START or orxANIM_EVENT_LOOP that fires, depending on your situation.
Also was hoping there is some built-in counter.
Regarding the ping-pong loop, I'm afraid that you'll need work arounds as well for now. I've been wanting to support negative time for anim update for quite a while, I guess that could be a good incentive to add this feature in the future (as well as a loop type).
Now, regarding frames and times, there's actual going to be a lot of changes there in a few weeks as it's my major target for the 1.7 release: enhancing drastically the animation system.
However, to answer your questions:
- orxAnim_GetLength() does return the duration, in seconds, of the animation
- the animations get updated at the same time as objects are, with the orxCLOCK_PRIORITY_LOW on the core clock. If you register your function with this priority or a lower one to the core clock, the code inside it will be executed after the animation update. However, if you want your code to run *before* the physics update, you can only use this priority, if you use orxCLOCK_PRIORITY_LOWER or _LOWEST, it'll be too late.
- you're right about using orxAnimPointer_SetTime() along with orxAnimPointer_GetCurrentTime(), that should work as intended. However I can add a link property in the future that specifies to keep the current time when transitioning, this way you wouldn't have to handle it manually yourself in any cases
Regarding the whole system, things will get much much easier to setup when I'm done with the enhancements, especially in your case where you need 8 variations on the same "scheme".
Here are a few things I plan to do:
- separate animation content into channels
- add custom animation channels, not just float values for custom events, should be much more flexible
- skeletal animation support (using their own dedicated channel, but that's not very relevant for you)
- much more concise animation & graph declaration, no more explicit anim or link lists, based on suggestions made by Sausage
- support for multiple variations on the same "graph template". For example, only one graph would be required in your case, all 8 variations would be achieved by modifying selection criteria at runtime.
Any suggestions about how to improve the system are welcome.
I guess it's one of those things, that pingpong loops could be put into orx, but then... if you need to tweak even one frame somewhere in the list, it would need to be broken out of a pingpong and become handwritten anyway.
Clean pingpong animations are reasonably rare aren't they? Enough that a long handed list is fairly justified?
Just a thought. Everyone's situation is different I suppose.
Should I open the issue for this one, too?
Ok, looking forward to it
That could work. But don't know what is better, using this system or waiting for the animation events? Are the animations event run inside the same update cycle as the animation? I mean, is animation event raised exactly at the given frame change or there could be some delay?
I don't care for physics.
Also, if I want to run some function after all the objects and other stuff has been updated, will it suffice to use the lowest priority for the clock and run it in it's handler? Or is there some other mechanism?
For now I'm not using links. I'm making all my transitions from code only.
That's nice list of additions.
Thank you for the info.
All of our idle animations are ping-pong.
Yeah, it depends on the type of the game you're making.
Would a ping pong loop setting save anyone any real development time? I suppose if you had stacks of ping pong animations.
But ignore me, I'm rambling.
Anyway, all my questions still stands I've implemented movement with orx. But I've used the iarwain suggestion, and have bind the animation update function to the lowest priority timer, to be executed after anything else (I don't know if this is true? Is there nothing executing after it?). But after I change the animation from walk -> idle, for some couple of frames, the object isn't rendered at all (it disappears). Then after the frames the object is shown again with the correct animation. I've tracked it that if I change the animation before the anim pointer is updated (that is, I bind my animation update function for normal priority clock) then everything is working fine. For now I've workaround. I wait for the next normal update and then I change the new animation. I'll be glad if someone could shed some light on this.
I'd recommend waiting for this one, as I'll need to think more about it during the pass I'm going to make on the animation system. I'll propose a code workaround at the end of this post for now.
I'd recommend using the LOW (not LOWER/LOWEST as your code would then happen after other things as well), but I'm sure it won't change with respect to the problem you described later. For that problem, I think the easiest way will be to send me a repro case (either a simple one or your current work in its current state, up to you).
There's no other mechanism for code ordering with a frame on the core clock beside priorities (well that's not entirely true, but let's focus on single threaded logic for now ).
The animation events are fired as soon as they are processed: no batching/delay. I can add a orxANIM_EVENT_UPDATE if need be.
For you ping-pong loop, you can have a piece of code that would run after your config data has been loaded (either driven by event or in your own sequence), go over all the sections and if there's a special key inside, let's say something called "IsPingPong" that is defined with the value true, you could then automatically create the "pong" part by reading the keys and appending them in reverse order. Should be pretty straightforward to write and all you'd need to do in config would be to add a IsPingPong = true to those anims. Or something like this if you prefer:
So I tested with the priorities LOW and LOWER and then it is working fine. So only with the LOWEST priority there is this behavior. So for now I will use the LOW priority. I could still make a repro case if you want (for the LOWEST behavior).
edit: So it looks like it is behaving odd when I use discrete GFX card (on integrated one, everything is working fine). But it isn't related to the clock update. I think I will prepare the test case. Between each animation change, the sprite is hidden for tiny amount of the time.
Also regarding the recommendation using the LOW priority. Why it is bad to run some things in the LOWER one beside that some stuff will be updated earlier? As to be clear, I don't use only 1 clock, but I have also the NORMAL priority clock. The majority of my logic is done using coroutines so I could dynamically change if I want to run the next code in the NORMAL update or LOW/LOWER/LOWEST update loop. I'm using the LOW priority clock only for animation now and for some camera movement code.
Yes having the event that would be raised when the animation is updated (or even better, if the animation frame was changed ) would solve all this problems (I think).
Regarding ping-pong, as I'm generating all the animation's .ini files with custom script, it easier for me to duplicate the frames for each ping-pong animation than going through all the animations defined and do it in orx
Anyway, thanks for You and others for helping me. I've rewritten the 90% of the stuff to orx so for 99% we're going to use orx. I've got some other suggestions, but will create separate thread for all of them here on the forum.
Thanks!
Oh, so you mean that with discrete GFX card, no matter which priority you use, you see the issue? What about integrated one? Does it work all the time, no matter which priority it is?
I only have access to hardware with single dedicated GPU, so it might be tricky for me to investigate if I understand correctly what you wrote.
It's not bad per se, it's just that the day you'll use collisions for example, it might trigger weird behavior until you remember the frame sequencing.
As for the priority, to be sure we're on the same page, the priority defines the order within a single clock, not the relation between many clocks, ie. on a single clock, callbacks will be called from the highest to the lowest priority.
That's what I meant sorry, that wasn't really clear. If you open an issue for this one, it should be rather straightforward to implement.
Sure!
I'm looking forward to hearing about those suggestions!
Of course.
OK.
I'll look at the update event soon.
Lemme know if you find any issues, I've only tested them very briefly.