GML How to get a sprite to play it's full animation before switching

FrostyTBB

Member
Hello! For a few days now I've trying to set up an animation to play when I press the space bar, and I want it to go through the full animation. However, It usually only plays for one or two frames before being overwritten by the idle or movement sprites, when I'd like for it to stay there for atleast a little longer. Image indexes didn't work, alarms broke it, and image speed does nothing. Any help would be amazing at this point.

GML:
  if (shank_delay > 0)
{
    shank_delay -= 1; // count down to the next shot by subtracting 1 from gun_delay
}

if (keyboard_check(vk_right)) {
    x+= 5;
    sprite_index = GuyWalk;
}


else if (keyboard_check(vk_left)) {
x-= 5;
    sprite_index = GuyWalk;   
}
else
{
    
sprite_index = GuyIdle;       
}



 if (speed>5)
  speed=5
 
if (keyboard_check_pressed(vk_space))
if (shank_delay <= 0)
 {
    bullet = instance_create_depth(x,y+60,layer,Bullet)
    bullet.direction = image_angle + -90
    shank_delay=45
    sprite_index = GuySwing;
    image_index = 0;
    
    
 }
 
image indexes don't reset automatically when you change sprites, to there's that you should know.
Also, you could use the animation end event, and make the state change there.
 

FrostyTBB

Member
Alright, I set image indexes to start at 0, but im kind of confused about the animation end event. Would I just put the idle sprite in there, so whenever any sprite index ends it just swaps to the idle sprite or what?

Thank you!
 
Yep. In the animation end event, just something like this
GML:
if((sprite_exists(spr_whatever)) && (sprite_index == spr_whatever)) {
    //Do stuff that will trigger at the end of the animation
}
 

Joe Ellis

Member
Using a state system is the ideal way to handle this type of problem. Say you have a variable "attacking" and check it before setting the sprite_index:

GML:
  if (shank_delay > 0)
{
    shank_delay -= 1; // count down to the next shot by subtracting 1 from gun_delay
}

if (keyboard_check(vk_right)) {
    x+= 5;
    if !attacking   
    {
    sprite_index = GuyWalk;
    }
}


else if (keyboard_check(vk_left)) {
x-= 5;
    if !attacking   
    {
    sprite_index = GuyWalk;
    } 
}
else
{
    if !attacking   
    {
    sprite_index = GuyIdle;
    }   
}



 if (speed>5)
  speed=5
 
if (keyboard_check_pressed(vk_space))
if (shank_delay <= 0)
 {
    bullet = instance_create_depth(x,y+60,layer,Bullet)
    bullet.direction = image_angle + -90
    shank_delay=45
    sprite_index = GuySwing;
    image_index = 0;
    attacking = true;
    
 }
And in the animation end event:

GML:
if attacking
{
attacking = false;
}
That's the most basic way of handling a kind of "state". It will get more complicated if you add more animations and states, then I'd recommend using separate scripts\functions for each state. That'll also make it easier to handle setting the sprites, cus say if you have a separate attacking state script that's run in the step event it'd look like this:


GML:
  if (shank_delay > 0)
{
    shank_delay -= 1; // count down to the next shot by subtracting 1 from gun_delay
}

if (keyboard_check(vk_right)) {
    x+= 2.5; //You could slow down movement while attacking
}


else if (keyboard_check(vk_left)) {
x-= 2.5;
}

 if (speed>5)
  speed=5
Then none of the stuff that messes up the sprites is even done during attacking. And you can use the animation end event to change the state back to "normal" when the attack animation has ended:

GML:
///Animation end event

if state = state_attacking
{state = state_normal}
"state_attacking" and "state_normal" would be separate functions\scripts, then to call them you'd simply put "state()" in the player's step event.
Or if you want a speed boost, create a method from the function and call that instead: "state_method()" in the step event.

GML:
///Animation end event

if state = state_attacking
{
state = state_normal
state_method = method(id, state_normal)
}
 

Joe Ellis

Member
Alternatively, you could use a method like this:

Make a variable "sprite_index_override", set it to undefined in the create event, and when the spacebar is pressed set it to the sprite you want to change sprite_index to, then in the end step event, simply do:

GML:
if sprite_index_override != undefined

{sprite_index = sprite_index_override}
So then just before drawing, any sprite_index changes will be overridden.
Then you can just use the animation end event to set sprite_index_override back to "undefined" and then the instance will go back to using the normal sprites again once the animation has finished.
 
Top