GMS 2 Sprites are not animating like they used to after being replaced

Hello GMS 2 users,

I'm pretty new to using Gamemaker Studio 2 and have been following Shaun Spalding's complete platformer tutorials, I'm currently on part 15. Before I posted here, I tried reading through the manual to try to solve the issue and usually I can, however, in this case, I'm not. My problem is that my sprites, which took the place of Shaun's sprites, aren't functioning; meaning the sprites in the tutorial that are labeled as Splayer, SplayerR (R= Run), SplayerA (A=Jump), and Splayerd (d=death). At first, when I replaced the running sprite it worked okay, but when I replaced every Splayer sprite I started to run into real issues. Sometimes I couldn't move my character and other times my character would flicker when I tried walking. I can only deduce that one of three things is causing the issue: (1) I have too many frames possibly because my sprites were animated using 3d models before being turned into 2d pixel sprites. (2) I tried adding a breathing animation to my Splayer sprite which previously had no animation, but removing it did not fix the issue. (3) There could be an issue with the collision box. I've tried playing with the frame rate as well as the collision box shape, but nothing has worked so far. Here is the code for Splayer, that still works for Shaun's sprites:


Create:

hsp = 0;
vsp = 0;
grv = 0.3;
walksp = 4;
controller = 0;
hascontrol = true;


Step:

//Get Player Input
if (hascontrol)
{
key_left = keyboard_check(vk_left) || keyboard_check(ord("A"));
key_right = keyboard_check(vk_right)|| keyboard_check(ord("D"));
key_jump = keyboard_check_pressed(vk_space);

if (key_left) || (key_right) || (key_jump)
{
controller = 0;
}

if (abs(gamepad_axis_value (0,gp_axislh)) > 0.2)
{
key_left = abs(min(gamepad_axis_value(0,gp_axislh),0));
key_right = abs(min(gamepad_axis_value(0,gp_axislh),0));
controller = 1;
}
if(gamepad_button_check_pressed(0,gp_face1))
{
key_jump = 1;
controller = 1;
}
}
else
{
key_right = 0;
key_left = 0;
key_jump = 0;

}
// Calculate Movement
var move = key_right - key_left;

hsp = move * walksp;

vsp = vsp + grv;

if (place_meeting(x, y+1,Owall)) and (key_jump)
{
vsp= -7;
}

//Horizontal Collision
if (place_meeting(x+hsp,y,Owall))
{
while (!place_meeting(x+sign(hsp),y, Owall))
{
x = x + sign(hsp);
}

hsp = 0;


}

x = x + hsp;

//Vertical Collision
if (place_meeting(x,y+vsp,Owall))
{
while (!place_meeting(x,y+sign(vsp),Owall))
{
y = y + sign(vsp);
}

vsp = 0;

}

y = y + vsp;

// Animation

if(!place_meeting(x,y+1,Owall))
{
sprite_index = SplayerA;
image_speed = 0;
if(sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
if(sprite_index == SplayerA)
{
audio_sound_pitch(snLanding,choose(0.8,1.0,1.1));
audio_play_sound(snLanding,4,false);
}
image_speed = 1;
if (hsp==0)
{
sprite_index = Splayer

}
else
{
sprite_index = SplayerR;
}
}

if(hsp != 0) image_xscale = sign(hsp)

Room Start:

///@desc Auto-Save
// overwrite old save
if (file_exists(SAVEFILE)) file_delete(SAVEFILE);

///Create a new save
var file;
file = file_text_open_write(SAVEFILE);

file_text_write_real(file,room);
file_text_close(file);

Animation End:

if (sprite_index == SplayerR) audio_play_sound(choose(snStep1,snStep2,snStep3,snStep4),1,false);


Oenemy:

/// desc Die

with(Ogun) instance_destroy();
instance_change(Opdead,true);
direction = point_direction(other.x,other.y,x,y);
hsp =lengthdir_x(6,direction);
vsp =lengthdir_y(4,direction)-2;
if(sign(hsp) != 0) image_xscale = sign(hsp);
 

SoapSud39

Member
I'm going to assume that your code has stayed the same from when the animations did work. You said that you've messed around with hitboxes, but you didn't specify how much, so try doing this if you haven't already:
Make a separate sprite of only one idle frame and make a rectangle collision mask in reference to that one (you can name it something like SplayerCollision), making sure that the origin is centered on the mask. Then, in your player object, set the mask to SplayerCollision instead of self. This will ensure that your hitbox stays the same even when you switch sprite indices. This will rule out weird hitbox shapes making your player stuck in the ground.
 
I'm going to assume that your code has stayed the same from when the animations did work. You said that you've messed around with hitboxes, but you didn't specify how much, so try doing this if you haven't already:
Make a separate sprite of only one idle frame and make a rectangle collision mask in reference to that one (you can name it something like SplayerCollision), making sure that the origin is centered on the mask. Then, in your player object, set the mask to SplayerCollision instead of self. This will ensure that your hitbox stays the same even when you switch sprite indices. This will rule out weird hitbox shapes making your player stuck in the ground.
Thanks for replying, I tried what you suggested and for the most part, it works. The character is no longer flickering against the ground, but she is now hovering when she is idle. The good news is part of the jump and idle animation are working and the walk animation works really well, she walks as she should now. There are still some issues, she disappears when she gets hit instead of playing her death animation, she jitters during her breathing animation, and she is unable to complete her jump animation before landing. Are these problems with the frame rate? Collision box? or something else? I should probably tell you that the size of each frame is 100px by 100 px which is bigger than the original sprite frame size. The code hasn't changed and the Mode and Type are automatic and rectangle, respectively, for all player sprites. I'm not sure if it is relevant or not, but my character was originally facing left when I imported her. I mirrored her after importing the sprite sheet so that she would facing to her right.
 

SoapSud39

Member
Okay, a few things.

For hovering and jittering, make sure all of your sprite origins are the same coordinates, and make sure that all of the frames for your jittering animation are lined up, to the pixel. Also line up frames between sprites if needed.

For jump animation, it might be that your image speed is too slow, if there's a set animation you're trying to complete. In that case, if you're planning on making variable jump heights later on, I would suggest rigging the frames to some code or script in the step event. If the problem is that she is landing before she touches the ground, position the sprite higher so that her feet line up with the y position of the bottom of your collision sprite mask.

For death object, I guess that was partially my fault, since I overlooked the instance_change() function at the bottom. Same idea with the player sprite, you'll want to set its collision mask in the object editor to be the collision object I told you to make. I'm guessing what's happening here is that you're on the ground when you test the death, and the death object hitbox goes lower than the other player hitbox, so it ends up inside the wall object and some weird collision interaction happens, teleporting your object out of the level. However, such an interaction shouldn't happen with your collision code, so it might be something else, but do the above anyway and see if anything gets fixed with death animation.

edit: importing and flipping usually only affects the positioning, which might be the cause for some of your issues. That is why I wrote to make sure your sprites are lined up.
 
Okay, a few things.

For hovering and jittering, make sure all of your sprite origins are the same coordinates, and make sure that all of the frames for your jittering animation are lined up, to the pixel. Also line up frames between sprites if needed.

For jump animation, it might be that your image speed is too slow, if there's a set animation you're trying to complete. In that case, if you're planning on making variable jump heights later on, I would suggest rigging the frames to some code or script in the step event. If the problem is that she is landing before she touches the ground, position the sprite higher so that her feet line up with the y position of the bottom of your collision sprite mask.

For death object, I guess that was partially my fault, since I overlooked the instance_change() function at the bottom. Same idea with the player sprite, you'll want to set its collision mask in the object editor to be the collision object I told you to make. I'm guessing what's happening here is that you're on the ground when you test the death, and the death object hitbox goes lower than the other player hitbox, so it ends up inside the wall object and some weird collision interaction happens, teleporting your object out of the level. However, such an interaction shouldn't happen with your collision code, so it might be something else, but do the above anyway and see if anything gets fixed with death animation.

edit: importing and flipping usually only affects the positioning, which might be the cause for some of your issues. That is why I wrote to make sure your sprites are lined up.
So I made several changes (1) I set the collision mask to Splayercollision for Opdead and it shows the first frame of the death animation when she dies. (2) I made sure all the origins for every frame of every sprite were the same and that stopped the hovering of the idle sprite, but there is still a bit of jittering that really puzzles me when she breathes. Her walk animation is still smooth but she sinks just a tiny bit when switching from the idle animation to the walking animation. I'm not sure what to do about the jump animation. I remember getting it to work before without changes to the code. The problem is that she jumps like Shaun's sprite and she doesn't bend her knees or anything. When you say line up the sprites, are you referring to the origin or how they are lined up on the sprite sheet? They play perfectly in the preview window, but I'm not sure if that means that they are lined up as they should be.
 

SoapSud39

Member
When you say line up the sprites, are you referring to the origin or how they are lined up on the sprite sheet? They play perfectly in the preview window, but I'm not sure if that means that they are lined up as they should be.
I meant both origin and lined up on the sprite sheet. Like if you put everything on the same sprite sheet they should line up as well, so stuff like sinking when switching animations shouldn't happen. So if you've done that, it's really weird that her position would still be shifting here and there, especially the breathing animation.

I also realized what you meant just now by your jump animation. It's not going because in Shaun's tutorial he sets the image_speed to 0. But you'll want to set it to 1 (and whatever you want in the sprite resource). But when you do, in your animation end event put something like
GML:
if sprite_index == SplayerA
{
    image_speed = 0;
}
which will stop your sprite from looping its animation if the sprite index is the jump one.

It might be a similar issue with your death animation, where your image speed is set to 0 for some reason before dying, so make sure you have "image_speed = 1" in the death object create event (or at the bottom of the code you posted up top) and make sure your image_speed changes are correct in the rest of the object. See if that works, and if not I'm also confused.

I also don't know what would be wrong with the jittery idle animation if it's not some weird one-pixel offset. If, after you try these + check sprite alignment again you still have issues, it might help to send a recording(s) of any issues you have left (especially the jittery one).
 
I meant both origin and lined up on the sprite sheet. Like if you put everything on the same sprite sheet they should line up as well, so stuff like sinking when switching animations shouldn't happen. So if you've done that, it's really weird that her position would still be shifting here and there, especially the breathing animation.

I also realized what you meant just now by your jump animation. It's not going because in Shaun's tutorial he sets the image_speed to 0. But you'll want to set it to 1 (and whatever you want in the sprite resource). But when you do, in your animation end event put something like
GML:
if sprite_index == SplayerA
{
    image_speed = 0;
}
which will stop your sprite from looping its animation if the sprite index is the jump one.

It might be a similar issue with your death animation, where your image speed is set to 0 for some reason before dying, so make sure you have "image_speed = 1" in the death object create event (or at the bottom of the code you posted up top) and make sure your image_speed changes are correct in the rest of the object. See if that works, and if not I'm also confused.

I also don't know what would be wrong with the jittery idle animation if it's not some weird one-pixel offset. If, after you try these + check sprite alignment again you still have issues, it might help to send a recording(s) of any issues you have left (especially the jittery one).
Okay, so I went back to Blender and made sure that all sprites faced to the right and that the camera coordinates were the same for each animation, then I created the sprites sheets and imported them into Game Maker. Now, all the animations work except for the jumping animation and by that I mean it won't finish her jump animation. I tried setting the image speed to different levels, but nothing changed. I'm wondering if it's too many frames or too complicated of a movement. The only other thing I saw, is when my character gets hit, she dies, but she restarts her animation if she is hit again before landing. Also, the lighting is different for each sprite, which I believe is more of a Blender issue and I can fix that. I'll post a video or a screenshot a little later today once I fix the lighting.
 
I meant both origin and lined up on the sprite sheet. Like if you put everything on the same sprite sheet they should line up as well, so stuff like sinking when switching animations shouldn't happen. So if you've done that, it's really weird that her position would still be shifting here and there, especially the breathing animation.

I also realized what you meant just now by your jump animation. It's not going because in Shaun's tutorial he sets the image_speed to 0. But you'll want to set it to 1 (and whatever you want in the sprite resource). But when you do, in your animation end event put something like
GML:
if sprite_index == SplayerA
{
    image_speed = 0;
}
which will stop your sprite from looping its animation if the sprite index is the jump one.

It might be a similar issue with your death animation, where your image speed is set to 0 for some reason before dying, so make sure you have "image_speed = 1" in the death object create event (or at the bottom of the code you posted up top) and make sure your image_speed changes are correct in the rest of the object. See if that works, and if not I'm also confused.

I also don't know what would be wrong with the jittery idle animation if it's not some weird one-pixel offset. If, after you try these + check sprite alignment again you still have issues, it might help to send a recording(s) of any issues you have left (especially the jittery one).
Here is the link to the game:
 

SoapSud39

Member
When I said image_speed, in reference to the jump animation, I meant this part:
GML:
if(!place_meeting(x,y+1,Owall))
{
    sprite_index = SplayerA;
    image_speed = 0;
    if(sign(vsp) > 0) image_index = 1; else image_index = 0;
}
in your player step code. You'll want to set that to "image_speed = 1" or it won't move no matter how fast you set it in the sprite resource.

For your death animation, I went back to Shaun's tutorial, episode 14, and I saw that he sets image_index to 1 when the body hits the ground because his death animation only has two frames. So in your death object you'll want to take out the line that says "image_index = 1" in the vertical collision code, and in the animation end event set "image_speed = 0" so that death animation doesn't loop (assuming you don't have it already). The "image_index = 1" is the reason why your death animation goes back to the second frame.
 
When I said image_speed, in reference to the jump animation, I meant this part:
GML:
if(!place_meeting(x,y+1,Owall))
{
    sprite_index = SplayerA;
    image_speed = 0;
    if(sign(vsp) > 0) image_index = 1; else image_index = 0;
}
in your player step code. You'll want to set that to "image_speed = 1" or it won't move no matter how fast you set it in the sprite resource.

For your death animation, I went back to Shaun's tutorial, episode 14, and I saw that he sets image_index to 1 when the body hits the ground because his death animation only has two frames. So in your death object you'll want to take out the line that says "image_index = 1" in the vertical collision code, and in the animation end event set "image_speed = 0" so that death animation doesn't loop (assuming you don't have it already). The "image_index = 1" is the reason why your death animation goes back to the second frame.
Okay, so all the animations work now. I fixed the death animation by decreasing the Frame Rate to 30 and applying the changes to the code that you suggested. The only thing that doesn't want to work is the jump animation and that is with changes in the code. I played with the image index to see if I could just get her to display some other part of the animation and it did, but it's almost like it skips all other frames to get to that one. You can kind of see from the video that her legs do move when she jumps, but it's almost like she doesn't have enough time to finish the animation. Would setting the speed to more than one help?
 

SoapSud39

Member
It seems like it skips all the other frames when you set the image_index because it does. I totally overlooked that line if(sign(vsp) > 0) image_index = 1; else image_index = 0;, and if it still looks like that in your code then that's the problem. If you take out that line, it'll run the actual animation from whatever frame your object is on, and then stop at the end because of the line I told you to put in animation end.

So what you can do now is take out that line. Up top, where you have your jump code, add image_index = 0 into the brackets of the if jump statement so that your jump animation starts at the beginning. With that, when you jump your animation will play from start to finish and then stop. If you want your animation to stop somewhere in the middle while mid jump (ie while going up) do this code
GML:
if(!place_meeting(x,y+1,Owall))
{
    sprite_index = SplayerA;
    image_speed = 1;
    if sign(vsp) < 0 and image_index > halfway_frame //if going up and animation passes halfway
    {
        image_index = halfway_frame;
    }
}
in addition to what I've written to do with the jump code. This will set your animation frame to your hypothetical half-way point (where she goes from jump to fall) if going up and the animation has reached that point. Otherwise, if your image_speed is 1 then the animation will continue on as normal and stop according to the animation end code.
 
It seems like it skips all the other frames when you set the image_index because it does. I totally overlooked that line if(sign(vsp) > 0) image_index = 1; else image_index = 0;, and if it still looks like that in your code then that's the problem. If you take out that line, it'll run the actual animation from whatever frame your object is on, and then stop at the end because of the line I told you to put in animation end.

So what you can do now is take out that line. Up top, where you have your jump code, add image_index = 0 into the brackets of the if jump statement so that your jump animation starts at the beginning. With that, when you jump your animation will play from start to finish and then stop. If you want your animation to stop somewhere in the middle while mid jump (ie while going up) do this code
GML:
if(!place_meeting(x,y+1,Owall))
{
    sprite_index = SplayerA;
    image_speed = 1;
    if sign(vsp) < 0 and image_index > halfway_frame //if going up and animation passes halfway
    {
        image_index = halfway_frame;
    }
}
in addition to what I've written to do with the jump code. This will set your animation frame to your hypothetical half-way point (where she goes from jump to fall) if going up and the animation has reached that point. Otherwise, if your image_speed is 1 then the animation will continue on as normal and stop according to the animation end code.
Okay, so now everything works. I made all the changes to the code as advised and set the image index to 68 for halfway_frame which is the peak of her jump. Thanks for all your help. I really appreciate it.
 
Top