Hi all! Basically as the subject says. Is there a way to calculate the length of time a character animation will take to play (based on the character's animation speed, the speed you play the animation, delays on frames, the game's framerate, etc) before you play it? Preferably in seconds or milliseconds?
Basically what I want to do is to run a tween that finishes exactly when the character's animation stops. The only way to do that is to determine how long the animation takes to play.
Any light-shedding appreciated!
-Dave
I suppose that may be possible.
Animation is played frame by frame, advancing a frame when the delay runs out. Frame delay is a sum (addition) of character's animation speed property (which is, counter-intuitively, a "delay"), and individual frame's delay.
The frame's delay is measured in "game updates" (aka "game frames", aka "game loops", aka "game ticks").
The real duration of a "game frame" is 1/GameSpeed seconds.
So, suppose you have N frames in animation.
The duration of full animation in game frames would be a
DUR_gf = SUM(each frame delay) + (animation speed * N)
And the duration in real time would be
DUR_s = DUR_gf / GameSpeed
Thanks CW! Just a few clarifications.
So for the first one, "SUM" is calculated by taking all the delays of each frame in the animation and adding them up?
And for "(animation speed * N)", which animation speed does this refer to? The speed you set for the character? Or the "delay" you set when you type in the Character.Animate command?
Quote from: Dave Gilbert on Mon 11/12/2023 14:23:01So for the first one, "SUM" is calculated by taking all the delays of each frame in the animation and adding them up?
That is correct.
Quote from: Dave Gilbert on Mon 11/12/2023 14:23:01And for "(animation speed * N)", which animation speed does this refer to? The speed you set for the character? Or the "delay" you set when you type in the Character.Animate command?
I had some strange memory twist, and forgot that character's property only refers to specific animations (walking, speaking).
So, the animation delay is a delay arg you pass into Animate.
EDIT: sorry I need to double check this, I will be back :)
EDIT2: alright, I confirmed, and Character's AnimationSpeed is basically "Walking Animation Speed" only. In the past it was also affecting Idle animation, but no more since 3.6.0.
I think the .Animate topic in the manual has a few details
https://adventuregamestudio.github.io/ags-manual/Character.html#characteranimate
https://adventuregamestudio.github.io/ags-manual/Object.html#objectanimate
It looks like with View, animate_speed, loop, direction and starting frame, it should be possible to create a function that takes these and figure it out the delay in ticks from these.
Quote from: Crimson Wizard on Mon 11/12/2023 14:27:27EDIT2: alright, I confirmed, and Character's AnimationSpeed is basically "Walking Animation Speed" only. In the past it was also affecting Idle animation, but no more since 3.6.0.
:shocked:
I could have sworn the character's animation speed effected all of their animations, and not just walking. It seems like I was wrong for over 20 years!
Anyway, thanks. I will fiddle.
-Dave
That's good to know, and strange to hear. I also thought that every animation was effected by that.
Maybe the character's animation speed should be renamed to character's walking animation delay ;-D
Quote from: Dave Gilbert on Mon 11/12/2023 14:07:15Basically what I want to do is to run a tween that finishes exactly when the character's animation stops. The only way to do that is to determine how long the animation takes to play.
Or just check in repeatedly execute if the character has stopped animating, and trigger the tween then? It's what I always do when I want to chain together non-blocking animations, for example.
Not sure how that would work, since I want the tween to finish when the animation stops, not for the tween to begin. I have an object that starts to move when the character beings her animation, and I want it to naturally come to a stop exactly when the character finishes her animation. Unless I'm misunderstanding what you mean.
Quote from: Dave Gilbert on Mon 11/12/2023 19:37:48Not sure how that would work, since I want the tween to finish when the animation stops, not for the tween to begin.
Ah, I totally misread this and thought you wanted the tween to
start when the animation stops. I was surprised that the answer was so convoluted, but this explains it :-D
I tested this with a basic animation and it seems to work:
// header
import int AnimateFrames(this Character*, int loop, int delay, RepeatStyle repeatStyle = eOnce, BlockingStyle blockingStyle = eBlock, Direction direction = eForwards, int frame = 0, int volume = 100);
// main
int AnimateFrames(this Character*, int loop, int delay, RepeatStyle repeatStyle, BlockingStyle blockingStyle, Direction direction, int frame, int volume) {
this.Animate(loop, delay, repeatStyle, blockingStyle, direction, frame, volume);
int frames = 0;
// TODO: handle eBackwards
for (int i = frame; i < Game.GetFrameCountForLoop(this.View, loop); i++) {
ViewFrame* vf = Game.GetViewFrame(this.View, loop, i);
frames += delay + vf.Speed + 1;
}
return frames;
}
Use like:
player.LockView(VIEW2);
int frames = player.AnimateFrames(0, 10, eOnce, eNoBlock, eForwards);
If you need milliseconds, use
int ms = (frames * 1000) / GetGameSpeed();
(Note: this only makes sense with eOnce and eNoBlock so one could skip these but I simply copied all Animate parameters)
Thanks Khris! One question. It looks like your function plays the animation and THEN counts the frames/ms length. Is there a reason why you played the animation beforehand?
Thanks Khris! One question. It looks like your function plays the animation and THEN counts the frames/ms length. Is there a reason why you played the animation beforehand?
edit: I tried it out myself and it appears that you don't need to play the animation beforehand! The method worked.
Before I had this animation of a little girl jumping off a table. The fact that her shadow kept jumping around bothered the heck out of me. Such a tiny trivial thing, but shadow jumping happens all over the game so I wondered if there was an easy way to fix it. Now I can! Thanks for the help, everyone!
(http://www.wadjeteyegames.com/temp/paula-shadow-1.gif) (http://www.wadjeteyegames.com/temp/paula-shadow-2.gif)
edit2: Weird. I went to edit but it double-posted instead. Sorry about that!
Quote from: Dave Gilbert on Tue 12/12/2023 13:36:38Thanks Khris! One question. It looks like your function plays the animation and THEN counts the frames/ms length. Is there a reason why you played the animation beforehand?
This basically happened on accident, I did the easy thing first (calling the actual Animate command) and later noticed I can leave it up there because it doesn't make a difference :)
The approach changes if you have a blocking animation; in that case you have to move the Animate call outside the counting function anyway.
Yeah, if the animation is non-blocking it saves me from having to type a second, almost identical line, which could be useful. But if the animation is blocking than it's more of a hindrance than a help. Easy enough to edit. Thanks for the help!