Legacy GM Keyboard_Check_Pressed Animation Not Working

E

Edward Griffith

Guest
Hi, I am programming a super smash type game and using coding to animate the sprite. I have several animations already in place such as idle, run and jump, and i am currently trying to implement a punch animation. However, when i set it up to 'Keyboard_Check_Pressed(Ord("F"))' (AKA punch), and have it to stop at the final frame of the animation (7), the game only plays the first frame of the punch and nothing else. Here is my code:
Code:
if (punch == 1)
{
    sprite_index = spr_player_punch
    if (image_index >= 7)
    {
        if (place_meeting(x, y+1, obj_platform))
        {
            if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
        }
        else
        {
            if (vsp !=0) sprite_index = spr_jump;
        }
    }
}
 
What is your image_speed set to? If it is 0, the animation won't play.

Where do you set punch to 1, and where do you set it back to 0? If you are setting it back to 0 when you release the punch key, that will stop the code from checking the image_index value.

Is the code you posted above running in the step event?
You should only need to set the sprite_index to spr_player_punch when the player presses the punch key, not every step.
 
E

Edward Griffith

Guest
What is your image_speed set to? If it is 0, the animation won't play.

Where do you set punch to 1, and where do you set it back to 0? If you are setting it back to 0 when you release the punch key, that will stop the code from checking the image_index value.

Is the code you posted above running in the step event?
You should only need to set the sprite_index to spr_player_punch when the player presses the punch key, not every step.
Hi, my image speed is set to 0.1, my punch is set to 1 when the 'f' key is pressed and i am not setting it back to 0. The problem is that it only plays the first frame of the animation and that is it. Also i did this in the same way i programmed my jump key (in the step even), but just tried removing it and creating a new event (keyboard pressed f) and adding 'sprite_index = spr_player_punch' but now i doesnt even play the animation at all. I am pretty confused.
 
When the player presses the punch key, are you setting image_index to 0? Because if you were in the middle of a previous animation, image_index won't be 0 by default.
 

ParodyKnaveBob

The Laughing Rogue
Howdy, Mr. Griffith, and welcome to the GMC. $:^ J

Have you tried stepping through the code in the debugger (while keeping an eye on the instance's image_index and image_speed)? I have a feeling you're repeatedly reseting the image_index -- but I'm about to fall asleep and could be wrong. $F^ }

Regards,
Bob
 
E

Edward Griffith

Guest
When the player presses the punch key, are you setting image_index to 0? Because if you were in the middle of a previous animation, image_index won't be 0 by default.
It works fine, and from the start, when i change it from 'pressed' to just holding "F" and does the full animation, but it loops and i want to to be done from just pressing it once instead of holding it down.
 

ParodyKnaveBob

The Laughing Rogue
Your last statement makes it sound like you set the sprite whenever no key is used.
Lots of wild guesses though. I still point at the debugger for my recommendation.
 
Sounds like you have some other code resetting the sprite / cancelling the animation.

Stepping through your logic with the debugger is the right thing to do at this point, or post the rest of your code that affects the sprite_index.
 
E

Edward Griffith

Guest
Sounds like you have some other code resetting the sprite / cancelling the animation.

Stepping through your logic with the debugger is the right thing to do at this point, or post the rest of your code that affects the sprite_index.
Alright, ill do a big code dump:
Code:
CREATION EVENT:
///initialise variables
image_speed = 0.1;
grav = 0.3;
hsp = 0;
vsp = 0;
jumpspeed = 12;
movespeed = 8;
orig_scale=image_xscale

STEP EVENT:
//Get player's input
key_right = keyboard_check(ord("D"));
key_left = -keyboard_check(ord("A"));
key_jump = keyboard_check_pressed(vk_space);
punch = keyboard_check(ord("F"));

//React to imputs
move = key_left + key_right;
hsp = move * movespeed;
if (vsp < 10) vsp += grav;

if (place_meeting(x,y+1,obj_platform))
{
    vsp = key_jump * -jumpspeed
}

//Horizontal collision
if (place_meeting(x+hsp,y,obj_platform))
{
    while(!place_meeting(x+sign(hsp),y,obj_platform))
    {
    x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

//Vertical collision
if (place_meeting(x,y+vsp,obj_platform))
{
    while(!place_meeting(x,y+sign(vsp),obj_platform))
    {
    y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;

//sprite control
if (hsp != 0) image_xscale = move*orig_scale;
if (place_meeting(x, y+1, obj_platform))
{
    if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
}
else
{
    if (vsp !=0) sprite_index = spr_jump;
}
if (punch == 1)
{
    sprite_index = spr_player_punch;
    if (image_index >= 7)
    {
        if (place_meeting(x, y+1, obj_platform))
        {
            if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
        }
        else
        {
            if (vsp !=0) sprite_index = spr_jump;
        }
    }
}
 

jaydee

Member
So from a read through of this code, assuming that this line:
punch = keyboard_check(ord("F"));

changed to keyboard_check_pressed(ord("F"));

then you would have exactly 1 frame of the punch animation and then return to idle (or whatever you are doing simultaneously).

This is because punch will reset to false in the 2nd step, which means this section:
Code:
if (punch == 1)
{
   sprite_index = spr_player_punch;
   if (image_index >= 7)
   {
       if (place_meeting(x, y+1, obj_platform))
       {
           if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
       }
       else
       {
           if (vsp !=0) sprite_index = spr_jump;
       }
   }
}
is skipped.

A really easily solution would be to add another variable, punchAnimation:

create:
punchAnimation = false;

step:
Code:
if (punch == 1 || punchAnimation)
{
   punchAnimation = true;
   sprite_index = spr_player_punch;
   if (image_index >= 7)
   {
       punchAnimation = false;
       if (place_meeting(x, y+1, obj_platform))
       {
           if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
       }
       else
       {
           if (vsp !=0) sprite_index = spr_jump;
       }
   }
}
Actually just rereading that, you could change the order of code in that particular segment to reduce it, because you already have assigned the correct sprite before changing it to the punch animation.

Code:
if(punch == 1 || punchAnimation)
{
  punchAnimation = true;
  if(image_index >= 7)
  {
   punchAnimation = false;
  }
  else
  {
    sprite_index = spr_player_punch;
  }
}
Finally, ideally you'd also set image_index to 0 when you first change the animation. So:
Code:
if(punch == 1 || punchAnimation)
{
 punchAnimation = true;
 if(punch == 1) image_index = 0;
 if(image_index >= 7) punchAnimation = false;
 else sprite_index = spr_player_punch;
}
 
E

Edward Griffith

Guest
So from a read through of this code, assuming that this line:
punch = keyboard_check(ord("F"));

changed to keyboard_check_pressed(ord("F"));

then you would have exactly 1 frame of the punch animation and then return to idle (or whatever you are doing simultaneously).

This is because punch will reset to false in the 2nd step, which means this section:
Code:
if (punch == 1)
{
   sprite_index = spr_player_punch;
   if (image_index >= 7)
   {
       if (place_meeting(x, y+1, obj_platform))
       {
           if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
       }
       else
       {
           if (vsp !=0) sprite_index = spr_jump;
       }
   }
}
is skipped.

A really easily solution would be to add another variable, punchAnimation:

create:
punchAnimation = false;

step:
Code:
if (punch == 1 || punchAnimation)
{
   punchAnimation = true;
   sprite_index = spr_player_punch;
   if (image_index >= 7)
   {
       punchAnimation = false;
       if (place_meeting(x, y+1, obj_platform))
       {
           if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
       }
       else
       {
           if (vsp !=0) sprite_index = spr_jump;
       }
   }
}
Actually just rereading that, you could change the order of code in that particular segment to reduce it, because you already have assigned the correct sprite before changing it to the punch animation.

Code:
if(punch == 1 || punchAnimation)
{
  punchAnimation = true;
  if(image_index >= 7)
  {
   punchAnimation = false;
  }
  else
  {
    sprite_index = spr_player_punch;
  }
}
Finally, ideally you'd also set image_index to 0 when you first change the animation. So:
Code:
if(punch == 1 || punchAnimation)
{
 punchAnimation = true;
 if(punch == 1) image_index = 0;
 if(image_index >= 7) punchAnimation = false;
 else sprite_index = spr_player_punch;
}
Wow, great explanation, thanks! Super in-depth and i understood everything. That got the punch to animate the whole way through. However, now it doesn't stop. It is super strange because looking at the code it should work fine, changing the punch animation to false and such. I even tried changing the code to make sure it stops yet nothing.
Code:
if(punch == 1 || punchanimation = true)
{
    punchanimation = true;
    if(punch == 1) image_index = 0;
    if(image_index >= image_number)
    {
        punchanimation = false;
        punch = 0
    }
    else sprite_index = spr_player_punch;
}
Also on a quick side note, the animation doesn't want to work in the air. It gets stuck on the first frame and occasionally glitches to the second but that's it. :/

Edit: Discovered you can glitch out of it by jumping on the last frame of the attack.
 
Last edited by a moderator:

jaydee

Member
Try changing image_number to image_number - 1. Image number is a count that starts at 1, image_index is an index that starts at 0.

Not sure what's causing the jumping glitch, will have to have a think about that one.
 
E

Edward Griffith

Guest
Try changing image_number to image_number - 1. Image number is a count that starts at 1, image_index is an index that starts at 0.

Not sure what's causing the jumping glitch, will have to have a think about that one.
Wow thanks that worked! I've now added a double jump as well as refined the punch, all i need to figure out is how to get it to play in the air, as well as make the player still horizontally while its punching. Any Ideas? Thanks!

Edit: NVM about the stopping while punching thing i figured it out! (After about 12 hours :/ ...) Still no idea on the punch in the air glitch tho :(
 
Last edited by a moderator:

jaydee

Member
Okay, I think I understand the jump glitch (although I'm only right if your jump animation is only 1 or 2 frames long).

Code:
//sprite control
if (hsp != 0) image_xscale = move*orig_scale;
if (place_meeting(x, y+1, obj_platform))
{
   if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
}
else
{
   if (vsp !=0) sprite_index = spr_jump;
}
if(punch == 1 || punchanimation = true)
{
   punchanimation = true;
   if(punch == 1) image_index = 0;
   if(image_index >= image_number - 1)
   {
       punchanimation = false;
       punch = 0
   }
   else sprite_index = spr_player_punch;
}
So what we have happening is this:
First step
1) In the first half of the sprite control, the sprite is set to spr_player_jump. Therefore image_number is set to the number of frames in the jump sprite.
2) In the second half of the sprite control, we've determined we're in a punch, set image_index to 0 and punchAnimation to true. The sprite is changed to spr_player_punch. image_number is now set to 7 (or however many frames you have).
3) At the end of this step, image_index is incremented to 1 by GMS.

Second step
1) In the first half of the sprite control, the sprite is once again set to spr_player_jump. image_number is set back to the number of frames in the jump sprite (which I'm assuming is 1 or 2).
2) Again we determine we're in a punch, but because this step the punch key isn't pressed, image_index is not reset to 0. So image_index (1) > image_number (1) - 1. So it assumes the punch animation is over, and doesn't reassign the sprite.

If I'm right, there is 3 easy ways to fix it.
1) Change the order of code so that the correct image is set before performing this check.
2) Hardcoding the number of frames into this check.
3) Using sprite_get_number(spr_player_punch) in place of image_number.

I think option 1 is probably the most elegant.
Code:
//sprite control
// Turn sprite first
if(hsp != 0) image_xscale = move * orig_scale;
// Now check if punching
if(punch == 1 || punchanimation == true)
{
  punchanimation = true;
  if(punch == 1) image_index = 0;
  if(image_index >= image_number -1) punchanimation = false;
  else sprite_index = spr_player_punch;
}
else if (place_meeting(x, y+1, obj_platform)) // Not punching, check if on ground
{
   if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
}
else // Not on ground
{
   if (vsp !=0) sprite_index = spr_jump;
}
 
E

Edward Griffith

Guest
Okay, I think I understand the jump glitch (although I'm only right if your jump animation is only 1 or 2 frames long).

Code:
//sprite control
if (hsp != 0) image_xscale = move*orig_scale;
if (place_meeting(x, y+1, obj_platform))
{
   if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
}
else
{
   if (vsp !=0) sprite_index = spr_jump;
}
if(punch == 1 || punchanimation = true)
{
   punchanimation = true;
   if(punch == 1) image_index = 0;
   if(image_index >= image_number - 1)
   {
       punchanimation = false;
       punch = 0
   }
   else sprite_index = spr_player_punch;
}
So what we have happening is this:
First step
1) In the first half of the sprite control, the sprite is set to spr_player_jump. Therefore image_number is set to the number of frames in the jump sprite.
2) In the second half of the sprite control, we've determined we're in a punch, set image_index to 0 and punchAnimation to true. The sprite is changed to spr_player_punch. image_number is now set to 7 (or however many frames you have).
3) At the end of this step, image_index is incremented to 1 by GMS.

Second step
1) In the first half of the sprite control, the sprite is once again set to spr_player_jump. image_number is set back to the number of frames in the jump sprite (which I'm assuming is 1 or 2).
2) Again we determine we're in a punch, but because this step the punch key isn't pressed, image_index is not reset to 0. So image_index (1) > image_number (1) - 1. So it assumes the punch animation is over, and doesn't reassign the sprite.

If I'm right, there is 3 easy ways to fix it.
1) Change the order of code so that the correct image is set before performing this check.
2) Hardcoding the number of frames into this check.
3) Using sprite_get_number(spr_player_punch) in place of image_number.

I think option 1 is probably the most elegant.
Code:
//sprite control
// Turn sprite first
if(hsp != 0) image_xscale = move * orig_scale;
// Now check if punching
if(punch == 1 || punchanimation == true)
{
  punchanimation = true;
  if(punch == 1) image_index = 0;
  if(image_index >= image_number -1) punchanimation = false;
  else sprite_index = spr_player_punch;
}
else if (place_meeting(x, y+1, obj_platform)) // Not punching, check if on ground
{
   if (move!=0) sprite_index = spr_player_running; else sprite_index = spr_player_idle;
}
else // Not on ground
{
   if (vsp !=0) sprite_index = spr_jump;
}
Wow man, thanks a ton, it worked. Thanks for helping me through this, it is a graded project for software dev in school. Ty
Edit: Hey again, new problem. I've tried to add knock back into my punch and it works great except it only knocks them back one way for one character, left for the main and right for the second.

Create:
Code:
recoilspeed = 10;
playerrecoil = -1
playerstop=-1;
Step:
Code:
//Attack
if(is_hit==true)
{
    sprite_index = spr_player2_hit;
    playerrecoil=5;
}
if (playerrecoil != -1)
{
    playerstop = 1
    playerrecoil -= 1;
    if (place_meeting(x-1, y, obj_hitbox))
    {
        direction = 0
    }
    else
    {
        direction = 180
    }
    speed = recoilspeed;
}

if (is_hit == true) && (place_meeting(x,y+1,obj_platform))
{
    is_hit = false;
    playerrecoil = -1
    speed = 0;
    playerstop = -1
}

if (playerrecoil = -1 && playerstop = 1)
{
    speed = 0;
    playerstop = -1;
}
I'm trying to make it so that if they get hit on the left they get knocked back to the right, and vice-versa but it not working
 
Last edited by a moderator:
Top