GML Need Help with editing Walking Sprite animation with Code

K

Krano Network Squirrell

Guest
I am trying to make a walking animation where my character uses 4 different sprites per direction, but when I try to edit Image Speed it only applies to one sprite! I need help, as soon as my character is moving it should play the animation and when it stops moving show the first frame facing the same direction, but it isn't working.
Code:
///actions
//movement AAA
key_right = keyboard_check(ord("D")) || (gamepad_axis_value(0,gp_axislh) > 0) || keyboard_check(vk_right);
key_left = keyboard_check(ord("A")) || (gamepad_axis_value(0,gp_axislh) < 0) || keyboard_check(vk_left);
Key_up = keyboard_check(ord("W")) || (gamepad_axis_value(0,gp_axislv) < 0) || keyboard_check(vk_up);
key_down = keyboard_check(ord("S")) || (gamepad_axis_value(0,gp_axislv) > 0) || keyboard_check(vk_down);

//react to imputs
var moveV = key_right - key_left;

var moveH =  Key_up - key_down;

hsp = moveV * movespeedwalk

vsp = moveH * movespeedwalk

//H Collision
if (place_meeting(x+hsp,y,obj_wall))
    {
        while (!place_meeting(x+sign(hsp),y,obj_wall))
        {
            x = x + sign(hsp);
        }
        hsp = 0;
    }
    
    x = x + hsp;

//V Collision
if (place_meeting(x,y+vsp,obj_wall))
    {
        while(!place_meeting(x,y+sign(vsp),obj_wall))
        {
            y = y + sign(vsp);
        }
        vsp = 0;
    }

y = y + vsp;

//animation

if (moveH > 0)
    {
        sprite_index = spr_neko_walkF
    }
    
if (moveH < 0)
    {
        sprite_index = spr_neko_walkB
    }

if (moveV > 0)
    {
        sprite_index = spr_neko_walkR
    }
    
if (moveV < 0)
    {
        sprite_index = spr_neko_walkL
    }
    
if (hsp * vsp = 0)
    {
        sprite_index = 0
        image_speed = 1
    }
 

CedSharp

Member
I am trying to make a walking animation where my character uses 4 different sprites per direction, but when I try to edit Image Speed it only applies to one sprite! I need help, as soon as my character is moving it should play the animation and when it stops moving show the first frame facing the same direction, but it isn't working.
Code:
///actions
//movement AAA
key_right = keyboard_check(ord("D")) || (gamepad_axis_value(0,gp_axislh) > 0) || keyboard_check(vk_right);
key_left = keyboard_check(ord("A")) || (gamepad_axis_value(0,gp_axislh) < 0) || keyboard_check(vk_left);
Key_up = keyboard_check(ord("W")) || (gamepad_axis_value(0,gp_axislv) < 0) || keyboard_check(vk_up);
key_down = keyboard_check(ord("S")) || (gamepad_axis_value(0,gp_axislv) > 0) || keyboard_check(vk_down);

//react to imputs
var moveV = key_right - key_left;

var moveH =  Key_up - key_down;

hsp = moveV * movespeedwalk

vsp = moveH * movespeedwalk

//H Collision
if (place_meeting(x+hsp,y,obj_wall))
    {
        while (!place_meeting(x+sign(hsp),y,obj_wall))
        {
            x = x + sign(hsp);
        }
        hsp = 0;
    }
   
    x = x + hsp;

//V Collision
if (place_meeting(x,y+vsp,obj_wall))
    {
        while(!place_meeting(x,y+sign(vsp),obj_wall))
        {
            y = y + sign(vsp);
        }
        vsp = 0;
    }

y = y + vsp;

//animation

if (moveH > 0)
    {
        sprite_index = spr_neko_walkF
    }
   
if (moveH < 0)
    {
        sprite_index = spr_neko_walkB
    }

if (moveV > 0)
    {
        sprite_index = spr_neko_walkR
    }
   
if (moveV < 0)
    {
        sprite_index = spr_neko_walkL
    }
   
if (hsp * vsp = 0)
    {
        sprite_index = 0
        image_speed = 1
    }
Also note that you are checking for 'hsp * vsp = 0'.
I dunno how GameMaker understands that line, but to me it means:

if( hsp * ( vsp = 0 ) ), which means:
if( hsp * 0 ) which means:
if( true )

You might want to change that to: "if( hsp*vps == 0 )" note the double equal operator.

Next, hsp * vsp means that if either of them is 0, this will make the condition true:

if hsp is 0, you get 0 * vsp, which is 0.
if vsp is 0, you get hsp * 0, which is 0.

Are you sure you didn't mean something like: if( hsp == 0 && vsp == 0 ) ?

I'm trying to understand your code here, sorry if I misunderstood it!
 
when it stops moving show the first frame facing the same direction, but it isn't working.
To show the first frame of an animation, you'll need to set the variable image_index to 0, and to stop the animation from playing automatically, set the image_speed to 0

sprite_index is the entire sprite itself, including all frames of animation.

image_index is a reference to the current frame of the sprite being displayed. You can read it or set it to control which frame is displayed.


Code:
if( hsp == 0 && vsp == 0 ) 
{
    image_index = 0
    image_speed = 0
}
else
{
    image_speed = 1
}
 
K

Krano Network Squirrell

Guest
Is there any specific reason to why you are setting sprite_index to 0 when the character is not moving? That would reset it to whatever sprite that is first-most in resource tree.
I need it to be where the sprite doesn't move when the object is not moving, so that the frame being rendered is frame 0, so when I was looking it up I was told that to set a certain frame of animation you set the Sprite_Index to whatever frame you need it to be. Hence, Sprite_index = 0. Correct me please if I am wrong in this thinking.
 

GMWolf

aka fel666
I need it to be where the sprite doesn't move when the object is not moving, so that the frame being rendered is frame 0, so when I was looking it up I was told that to set a certain frame of animation you set the Sprite_Index to whatever frame you need it to be. Hence, Sprite_index = 0. Correct me please if I am wrong in this thinking.
You are mistaking spritr_index for image_index.

image_index: the fame number of the current sprite.

sprite_index: the sprite itself.
 
K

Krano Network Squirrell

Guest
Also note that you are checking for 'hsp * vsp = 0'.
I dunno how GameMaker understands that line, but to me it means:

if( hsp * ( vsp = 0 ) ), which means:
if( hsp * 0 ) which means:
if( true )

You might want to change that to: "if( hsp*vps == 0 )" note the double equal operator.

Next, hsp * vsp means that if either of them is 0, this will make the condition true:

if hsp is 0, you get 0 * vsp, which is 0.
if vsp is 0, you get hsp * 0, which is 0.

Are you sure you didn't mean something like: if( hsp == 0 && vsp == 0 ) ?

I'm trying to understand your code here, sorry if I misunderstood it!
I think you are understanding, this part of the Code is trying to sense if the object is or is not moving, so if HSP is set to 0 and VSP is set to 1, then the game plays the animation, but if both HSP and VSP is 0 then it won't.
 
K

Krano Network Squirrell

Guest
You are mistaking spritr_index for image_index.

image_index: the fame number of the current sprite.

sprite_index: the sprite itself.
Ah, thanks I was wondering what was going on. That must be my mistake, sorry.
 
K

Krano Network Squirrell

Guest
To show the first frame of an animation, you'll need to set the variable image_index to 0, and to stop the animation from playing automatically, set the image_speed to 0

sprite_index is the entire sprite itself, including all frames of animation.

image_index is a reference to the current frame of the sprite being displayed. You can read it or set it to control which frame is displayed.


Code:
if( hsp == 0 && vsp == 0 )
{
    image_index = 0
    image_speed = 0
}
else
{
    image_speed = 1
}
I will insert this into the game now, currently there is something wrong with Game Maker Studio where on this laptop it will not let me test the game. So when I get back from where I work I should be fine. Thanks for your help.
 

GMWolf

aka fel666
I think you are understanding, this part of the Code is trying to sense if the object is or is not moving, so if HSP is set to 0 and VSP is set to 1, then the game plays the animation, but if both HSP and VSP is 0 then it won't.
You are forgetting basic mathematics.
0 * 1 is still 0.
So you just hsp OR vsp have to be 0, not both.

More importantly: don't try to be clever. Write what you mean. You want to check if both vsp and hsp is 0. So write that!
Code:
if( vsp == 0 and hsp == 0)
That way you don't make stupid mistakes.


You should also use == rather than = to check equality. It reduces confusion.
 

CedSharp

Member
Here is an example code for movements that I would've coded in your situation:
Code:
// Define some local variable in advance to avoid using
// the 'var' keyword everywhere.
var key_right, key_left, key_up, key_down, hsp, vsp, dist, target_sprite;

// Get input
key_right = keyboard_check(ord("D")) || (gamepad_axis_value(0,gp_axislh) > 0) || keyboard_check(vk_right);
key_left = keyboard_check(ord("A")) || (gamepad_axis_value(0,gp_axislh) < 0) || keyboard_check(vk_left);
key_up = keyboard_check(ord("W")) || (gamepad_axis_value(0,gp_axislv) < 0) || keyboard_check(vk_up);
key_down = keyboard_check(ord("S")) || (gamepad_axis_value(0,gp_axislv) > 0) || keyboard_check(vk_down);

// Convert input to direction
hsp = key_right - key_left;
vsp = key_down - key_up;

// Horizontal Movement
dist = hsp*movespeedwalk;
while( dist > 0 && place_meeting(x+dist, y, obj_wall) ) dist--;
x += dist;

// Vertical Movement
dist = vsp*movespeedwalk;
while( dist > 0 && place_meeting(x, y+dist, obj_wall) ) dist--;
y += dist;

// Update sprite
if( hsp == 0 && vsp == 0 ) {
    // Player is not moving, show first frame and stop animation
    image_index = 0;
    image_speed = 0;
}
else {
    // Find which sprite should be displayed
    if( hsp > 0 ) target_sprite = spr_player_walk_right;
    else if( hsp < 0 ) target_sprite = spr_player_walk_left;
    if( vps > 0 ) target_sprite = spr_player_walk_down;
    else if( vsp < 0 ) target_sprite = spr_player_walk_up;

    // Change sprite only if it's not the correct one,
    // otherwise it will reset the animation!
    if( sprite_index != target_sprite ) sprite_index = target_sprite;

    // Set the animation speed since player is currently moving
    image_speed = 1;
}
Hopefully this code proves useful for you :)
 

GMWolf

aka fel666
Here is an example code for movements that I would've coded in your situation:
Code:
// Define some local variable in advance to avoid using
// the 'var' keyword everywhere.
var key_right, key_left, key_up, key_down, hsp, vsp, dist, target_sprite;

// Get input
key_right = keyboard_check(ord("D")) || (gamepad_axis_value(0,gp_axislh) > 0) || keyboard_check(vk_right);
key_left = keyboard_check(ord("A")) || (gamepad_axis_value(0,gp_axislh) < 0) || keyboard_check(vk_left);
key_up = keyboard_check(ord("W")) || (gamepad_axis_value(0,gp_axislv) < 0) || keyboard_check(vk_up);
key_down = keyboard_check(ord("S")) || (gamepad_axis_value(0,gp_axislv) > 0) || keyboard_check(vk_down);

// Convert input to direction
hsp = key_right - key_left;
vsp = key_down - key_up;

// Horizontal Movement
dist = hsp*movespeedwalk;
while( dist > 0 && place_meeting(x+dist, y, obj_wall) ) dist--;
x += dist;

// Vertical Movement
dist = vsp*movespeedwalk;
while( dist > 0 && place_meeting(x, y+dist, obj_wall) ) dist--;
y += dist;

// Update sprite
if( hsp == 0 && vsp == 0 ) {
    // Player is not moving, show first frame and stop animation
    image_index = 0;
    image_speed = 0;
}
else {
    // Find which sprite should be displayed
    if( hsp > 0 ) target_sprite = spr_player_walk_right;
    else if( hsp < 0 ) target_sprite = spr_player_walk_left;
    if( vps > 0 ) target_sprite = spr_player_walk_down;
    else if( vsp < 0 ) target_sprite = spr_player_walk_up;

    // Change sprite only if it's not the correct one,
    // otherwise it will reset the animation!
    if( sprite_index != target_sprite ) sprite_index = target_sprite;

    // Set the animation speed since player is currently moving
    image_speed = 1;
}
Hopefully this code proves useful for you :)
nooo, what have you done! oh well... it is nice code.
 

Simon Gust

Member
Code:
    // Find which sprite should be displayed
    if( hsp > 0 ) target_sprite = spr_player_walk_right;
    else if( hsp < 0 ) target_sprite = spr_player_walk_left;
    if( vps > 0 ) target_sprite = spr_player_walk_down;
    else if( vsp < 0 ) target_sprite = spr_player_walk_up;
You are violating twin-statements, how dare you!?
Look ->
Code:
if( hsp < 0 ) target_sprite = spr_player_walk_left;
else 
if( hsp > 0 ) target_sprite = spr_player_walk_right;

if( vps < 0 ) target_sprite = spr_player_walk_up;
else 
if( vsp > 0 ) target_sprite = spr_player_walk_down;
Also, left goes before right and up before down.
Totally not supercilious.
 

CedSharp

Member
You are violating twin-statements, how dare you!?
Look ->
Code:
if( hsp < 0 ) target_sprite = spr_player_walk_left;
else
if( hsp > 0 ) target_sprite = spr_player_walk_right;

if( vps < 0 ) target_sprite = spr_player_walk_up;
else
if( vsp > 0 ) target_sprite = spr_player_walk_down;
Also, left goes before right and up before down.
Totally not supercilious.
I always code with those rules:

For any braces, no space before "if __ (condition)", but spaces inside "if( __ condition __ )"
If there is only one statement to execute and it fits inside 120 columns, then include it on same line.
Otherwise, open a block on same line and indent it's content:

Code:
if( condition ) statement;
if( condition ) {
    statement;
}
I treat "else if" and "else" as an exception. They are the only control statement that I won't seperate with an empty line:

Code:
if( condition1 ) statement;

if( condition2 ) statement;

if( condition3 ) statement;
else if( condition4 ) statement;
else {
  statement_1;
  statement_2;
}
I follow many different rules like that ( I work in web development, more specifically Javascript with Babel and NodeJS ),
and trust me, how you do it is not important, as long as you always stick to the same rules.

If I can tell you are the one who wrote the code simply by it's style, that means you're doing a good job ;)
 

CedSharp

Member
nooo, what have you done! oh well... it is nice code.
I usually don't like to provide the direct answer, but in this case, he misunderstand what the variable stands for, so hopefully
by comparing his code to this working answer, he'll understand why his version didn't work.
 
Top