Animation handling

edited December 2014 in Help request
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

  • edited December 2014
    I'll try to make suggestions on a couple of your questions:
    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.

    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:
    [WalkAnim]
    DefaultKeyDuration  = 0.2; 
    KeyData1            = walk1
    KeyData2            = walk2
    KeyData3            = walk3
    KeyData4            = walk4
    KeyData5            = walk5
    KeyData6            = walk4
    KeyData7            = walk3
    KeyData8            = walk2
    
    Also is there some counter of how many animation loops has been played already?

    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.
  • edited January 2015
    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:
    [WalkAnim]
    DefaultKeyDuration  = 0.2; 
    KeyData1            = walk1
    KeyData2            = walk2
    KeyData3            = walk3
    KeyData4            = walk4
    KeyData5            = walk5
    KeyData6            = walk4
    KeyData7            = walk3
    KeyData8            = walk2
    
    Yes, was hoping to not to use this "workaround" :)
    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.
  • edited January 2015
    No internal loop counter, sorry, but I could easily add one. If you want it, feel free to open an issue for that. :) For now you can increment your own counter when you receive the loop event.

    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. :)
  • edited January 2015
    Trigve wrote:
    Yes, was hoping to not to use this "workaround" :)

    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.
  • edited January 2015
    No internal loop counter, sorry, but I could easily add one. If you want it, feel free to open an issue for that. :) For now you can increment your own counter when you receive the loop event.
    I see. By opening the issue you mean here on the forum or on the bitbucket?
    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). :)
    Should I open the issue for this one, too?
    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.
    Ok, looking forward to it :)
    - 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.
    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?
    - 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
    For now I'm not using links. I'm making all my transitions from code only.
    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. :)
    That's nice list of additions.

    Thank you for the info.
  • edited January 2015
    sausage wrote:
    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.
    I think I don't get it :)
    Clean pingpong animations are reasonably rare aren't they? Enough that a long handed list is fairly justified?
    All of our idle animations are ping-pong.
    Just a thought. Everyone's situation is different I suppose.
    Yeah, it depends on the type of the game you're making.
  • edited January 2015
    Yep sorry I wasn't clear. I figured that people would start off setting up a ping pong animation, then after a while would decide to tweak a frame here and there, eg: extend the timing of the second last frame... therefore it would no longer be a ping pong animation, and have to be written out longhand.

    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. :)
  • edited January 2015
    sausage, we do it only for time saving... also I wasn't correct at my previous post, we aren't using ping-pong for *all* the idles, some of them are only "single one". But I think that ping-pong animation need to be design correctly to be for some use.

    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.
  • edited January 2015
    Trigve wrote:
    I see. By opening the issue you mean here on the forum or on the bitbucket?
    On the bitbucket repository, please, and you can assign it to me directly.
    Should I open the issue for this one, too?

    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.
    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?

    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:
    [PingPong]
    IsPingPong = true
    
    [MyRegularAnim]
    ...
    
    [MyPingPongAnim@PingPong]
    ...
    
  • edited January 2015
    On the bitbucket repository, please, and you can assign it to me directly.
    Ok I've add it there.
    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).
    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.
    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.
    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.
  • edited January 2015
    Trigve wrote:
    Ok I've add it there.

    Thanks!
    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.

    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.
    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.

    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.
    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).

    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.
    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 :)

    Sure! :)
    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.

    I'm looking forward to hearing about those suggestions!
  • edited January 2015
    iarwain wrote:
    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.
    With integrated it doesn't work only with LOWEST clock priority. I think you should see the behavior on your GFX. I've added the better description in the mail.
    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.
    Of course.
    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.
    OK.
  • edited January 2015
    By the way, I got your PM but didn't receive any email after that. Did you get the opportunity to send the repro case?

    I'll look at the update event soon.
  • edited January 2015
    Yeah, I've sent it right away after getting your response. Will resend it.
  • edited January 2015
    As you've probably noticed, I've added the loop counter as well as the orxANIM_EVENT_UPDATE when a new key is selected within an animation (not sent for the first key, if you want to consider this, then you'll need to handle orxANIM_EVENT_START as well).

    Lemme know if you find any issues, I've only tested them very briefly. :)
  • edited January 2015
    Yes, I've noticed and I am grateful for it:) If I find some issue, I'll report it.
Sign In or Register to comment.