• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!

GML [SOLVED] Draw tile set after player being idle for specific time

Aardvark

Member
Hi!

I'm fairly new to GMS 2 and GML but I'm a quick learner.

I've set-up basic animations for my player based on the direction it's going (8 directions). What I'd like to do is start a frame by frame animation from a given tile set after the player is idle for let's say 5 seconds.

Here is what I have so far :

CREATE EVENT
Code:
/// @description Key variables

//---------PLAYER SPEED
spd = 0;                //Horizontal and vertical speed
//grv = 0.3;            //Gravity speed
n_spd = 3;                //Walk speed
r_mod = 1.5;            //Run speed modifier
d_mod = 1/sqrt(2);        //Diagonal speed modifier
r_spd = r_mod*n_spd;    //Run speed

//---------CHARACTER SPRITE
x_frame = 0;
y_frame = 0;

x_offset = sprite_get_xoffset(mask_index);
y_offset = sprite_get_yoffset(mask_index);

spr_base = spr_player;
spr_idle = spr_player_idle;

//---------IDLE AMINATION TIMER
room_speed = 60;
idl_anim_timer = room_speed * 5;
STEP EVENT :

I'll skip all the key detections, diagonal speed correction and collision stuff, only the timer logic :
Code:
if (moveX == 0 && moveY == 0)    idl_anim_timer -= 1;
else                            idl_anim_timer = room_speed * 5;
DRAW EVENT :
Code:
/// @description Draw Player
// You can write your code in this editor
var anim_length = 8; //Number of frame per loop
var frame_size = 64;
var anim_speed = 48;
var anim_speed_idle = 20;

if      (moveY < 0) && (moveX == 0)   y_frame = 0;    //Frames for UP direction
else if (moveX < 0) && (moveY == 0)   y_frame = 1;    //Frames for LEFT direction
else if (moveY > 0) && (moveX == 0)   y_frame = 2;    //Frames for DOWN direction
else if (moveX > 0) && (moveY == 0)   y_frame = 3;    //Frames for RIGHT direction
else if (moveX < 0) && (moveY < 0)    y_frame = 4;    //Frames for UPLEFT direction
else if (moveX < 0) && (moveY > 0)    y_frame = 5;    //Frames for DOWNLEFT direction
else if (moveX > 0) && (moveY > 0)    y_frame = 6;    //Frames for DOWNRIGHT direction
else if (moveX > 0) && (moveY < 0)    y_frame = 7;    //Frames for UPRIGHT direction
else                                  x_frame = 0;    //Frame while not moving

var xx = x - x_offset;
var yy = y - y_offset;

if (x_frame + (anim_speed/60) < anim_length)        { x_frame += anim_speed/60; }
else if (x_frame < anim_length - 1) && (key_run)    { x_frame += (r_mod*anim_speed)/60; }
else                                                { x_frame = 0; }

//---------DRAW SPHERE BASE
//spr_base is the tile containing all the sphere frames
draw_sprite_part(spr_base, 0, floor(x_frame)*frame_size, y_frame*frame_size, frame_size, frame_size, xx, yy);

//---------DRAW SPHERE LIGHT AFTER IDLE
if (moveX == 0 && moveY == 0 && idl_anim_timer < 0) {

    //Draw timer for troubleshooting
    draw_set_color(c_white);
    draw_text(50, 50, "Timer: " + string(idl_anim_timer));
    draw_text(50, 70, "Timer in seconds: " + string(idl_anim_timer/room_speed));
    draw_text(50, 90, "x_frame value: " + string(x_frame));
    draw_text(50, 110, "y_frame value: " + string(y_frame));

    //Draw sprite from spr_idle tile over spr_base
    draw_sprite_part(spr_idle, 0, floor(x_frame)*frame_size, y_frame, frame_size, frame_size, xx, yy);
    if (x_frame + (anim_speed/60) < anim_length)        { x_frame += anim_speed/60; }
}
The "Light" animation is what I want to draw over after a 5 seconds idle.

x_frame is the X location on the tile set, y_frame is the Y location on the tile set.

There is clearly something I don't understand, I want to loop the sprite part on the last y_frame location, in the x_frame direction, until the player move again. but nothing appears. The x_frame seems to only increment 1 frame and stalls there.

Any ideas?

Thanks!
 
Last edited:

Alexx

Member
I would suggest looking into enums / states.
This would make it much much easier to manage.

I have an example for 4 directions if you'd like it.
 

Aardvark

Member
I would suggest looking into enums / states.
This would make it much much easier to manage.

I have an example for 4 directions if you'd like it.
Thanks for your suggestion and your offer, but my 8 directions works really well that way. Each tile set are exactly the same in term of size and frames, when I want to draw a specific sprite over my base player, I can add a new "draw_sprite_part()" line while referring to another tile set. I think it's easily manageable that way.

To be honest, I was hoping for a more "detailed" answer on how to make this work...
 

Nidoking

Member
You've got a big if-else ladder that sets y_frame and then ends with "else x_frame = 0;" That's resetting your x_frame to 0 every time. You probably meant to set y_frame to something there.
 

Aardvark

Member
You've got a big if-else ladder that sets y_frame and then ends with "else x_frame = 0;" That's resetting your x_frame to 0 every time. You probably meant to set y_frame to something there.
It's set this way so when the player stops, we see the x_frame = 0 at the last y_frame location. Ex: I press the "D" key, I go to the "Right" direction, meaning moveX is +1, and moveY is 0, my Right animation strip is located at the position 3 on my tile set. Animation loops at that y_frame. When the player stops, that animation strip stays active, but shows the first x_frame, which is 0. In that case, y_frame = 3 until a new direction is given by the player.

I have an idle tile set (spr_idle) that have a blinking light located at the right position for the base tile set (spr_base). I want to loop the strip at y_frame = 3 on spr_idle, over spr_base, only after being idle for 5 seconds.
 

Nidoking

Member
I have an idle tile set (spr_idle) that have a blinking light located at the right position for the base tile set (spr_base). I want to loop the strip at y_frame = 3 on spr_idle, over spr_base, only after being idle for 5 seconds.
I understand now, but the fact remains that any time the player is not moving, x_frame is reset to 0 each step. This is why you're not seeing your animation. Try using a different variable, such as x_idle_frame, to keep track of the frame in the idle animation so that you're not conflicting with the variable that stores the character sprite.
 

Aardvark

Member
I understand now, but the fact remains that any time the player is not moving, x_frame is reset to 0 each step. This is why you're not seeing your animation. Try using a different variable, such as x_idle_frame, to keep track of the frame in the idle animation so that you're not conflicting with the variable that stores the character sprite.
Ahhh thanks! You're right! Like you said I've created an x_idle_frame = 0 variable and changed the idle drawing section to :

Code:
//---------DRAW SPHERE LIGHT AFTER IDLE
if (moveX == 0 && moveY == 0 && idl_anim_timer < 0) {
    //Draw sprite from spr_idle tile over spr_base
    draw_sprite_part(spr_idle, 0, floor(x_idle_frame)*frame_size, y_frame*frame_size, frame_size, frame_size, xx, yy);
    if (x_idle_frame + (anim_idle_speed/60) < anim_length)    { x_idle_frame += anim_idle_speed/60; }
    else                                                    { x_idle_frame = 0; }
}
It works! Thanks!
 
Top