1

Hi Everyone!

I'm having an issue I can't seem to solve on the DATLib side of things.
I'm wondering If anyone can help me sort it out?

To set the stage lets say you have two near identical running animations.
(Animations can be any number of frames...The important part is both animations have the exact same number of frames and are near identical)

Animation 1 (Standard Run)
Animation 2 (Shoot while Running)

In both cases the leg animations are identical but the upper body changes to fire a weapon if the users presses the shoot button.

I have coded a near seamless frame swap

1. Lets say you player is on run frame 4 and the user presses the fire button.
2. The animation changes to frame 4 of the shoot animation at that exact moment the player presses the shoot button.

This works pretty well. The functions being used to achieve this could be:

aSpriteSetAnimStep, or aSpriteSetAnimStep2

EX: aSpriteSetAnimStep (&playerE->gfx[0]->sprite, playerE->anim.A_RUN_RECOIL, playerE->gfx[0]->sprite.stepNum);
Side Note: I believe both functions work in this case.
The difference is the first function will ignore a request to call the animation that is currently running but in our case that doesn't matter as we are calling an entirely different animation.

Anyway here is the issue:

Assuming your frames have the standard 5 frame duration. EX: The frame is held for 5 frames then the next animation frame is displayed

If the Frame 4 was on it's 4th hold frame this means it is just about to transition to frame 5 but then the users presses the fire button at that moment and the timing gets messed up at that point.

The user see's a seamless transition to a near identical frame however the timing is reset. So instead of frame 4 being held for 5 frames it is held for like 9 frames.

4 (Old frame held for 4 frames at the time of user input) + 5 (New Frame is programmed to hold for 5 frames) = 9 frames user see's that frame for too long...

Another Example: Frame 4 is typically held for 5 frames....

1. Frame 4 is on it's 4th hold frame at the time of user intervention.
2. New near identical frame 4 is loaded however the 'duration' is reset to 0
Now we have the 4 initial frames we saw frame 4 for plus we have to wait 5 identical frames.
3. The fluidity of the animation is lost as the user realizes one of the run frame is held for slightly longer then it should be.

In this case a frame that should appear for 5 frames appears for 9.

The Animator tool in DATLib does allow the user to stipulate duration to get the perfect timing on your animations.

The only mention of the duration is found here:

typedef struct animStep { sprFrame *frame; Pointer to frame info short shiftX; Frame X displacement from origin short shiftY; Frame Y displacement from origin ushort duration; Number of frame to display } animStep;
The struct breakdown is accompanied with this note in the documentation:

spriteInfo, animStep and sprFrame structures are generated by the buildchar and animator tools. Holds infos about animated sprite frames and animations.
Which tells me the animations must be reading from this information when loading frames and animations.

I hope what I have written makes sense. I don't want the timing to reset when a new animation is called. I want the previous frame timing to be carried over to the new animation frame.

This function does not exist as I am just adding a new parameter here but this pretty much sums it up. Does anyone know if this is possible?

EX: aSpriteSetAnimStep (&Sprite, NewAnimationID, sprite.stepNum, sprite.doNotResetDuration);

2

I don't know if I got your situation very well, but I wouldn't put legs in any animation.

Legs must be isolated, the trunk part woiuld be switched.
So legs and trunk* must simply be moved along accordingly.

3

Sorry I know I'm terrible at explaining this one.

I agree the smart thing to do would be to have the top half and bottom half of the body separated for a run/shoot animation. However if you wanted to save sprites you could have the animations merged. Its more work up front but once it is setup you'll get more sprites on screen in the end.

This scenario is not isolated to a run/shoot animation but to manually adjusting DATLibs frame durations in real time.

DATLib allows the user to stipulate how long a frame is held for in the animator tool.

EX: This frame will be held for a duration of 5 frames then it will switch to the next frame in the sequence however maybe the next frame is held for 3 frames etc...

In my case I have two animation sequences with the exact same number of frames and the exact same tick durations on each frame.

Complimenting animations if you want to call it that.

When I jump from one animation sequence to the next as long as the step matches it is a seamless transition between animations.

Animation 1 is on frame 4
Now Animation 2 is on frame 4

Almost seamless however in the process of switching to Animation 2 from Animation 1 the frame tick timing is reset and that is my issue.

If Animation 1 and 2 have a hold of 5 ticks before the frame swaps and at the time of the swap any ticks have elapsed those ticks are omitted at the time of the swap so now the frame the animation swap occurs on is on screen longer then it should be.

Ex: Perform an animation swap on a frame that holds for 5 ticks. Assuming the frame is on tick 4 at the time of the swap the new animation loaded should only show the new frame loaded briefly for 1 tick. Instead it resets the ticks the frame is displayed for to 5 ticks again.

I get that in practice DATLib just thinks you are loading a new animation and loads the new durations accordingly. Can I manually force the tick counter to a value of my choosing? In this case the value of the tick counter would be a copy of the value of the previous animations tick counter at the time the animation was swapped.

I hope this makes more sense I'm bad at explaining this one.