1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

Need help implementing state machines

Discussion in 'Programming' started by Bobcraft420, Nov 7, 2019 at 1:40 PM.

  1. Bobcraft420

    Bobcraft420 Member

    Joined:
    Thursday
    Posts:
    1
    Hey, so I have been working on a top down RPG and I am trying to implement a state system to switch the players states i.e ( idle, movement, sprint,attack,etc). I'm fairly new to GMS(I'm using GMS 1.4.9999) and have some minor coding experience.
    The problem I am stuck with is that when the player is in the idle state it does not switch to the attack state.
    This is my idle state code
    Code:
    scr_get_input();
    //if moving
    if (up_key || down_key || right_key || left_key)
    {
        state = scr_move_state;   
    }
    //if attacking
    if(attack_key)
    {
        state = scr_attack_state;
    }
    //if sprite is facing down
    if(sprite_index = spr_player)
    {
        image_speed = 0.1;
        sprite_index = spr_male_idle
    }
    //if sprite is facing up
    if(sprite_index = spr_male_up)
    {
        sprite_index = spr_male_idleu
        image_speed = 0.1;
    }
    //if sprite is facing right
    if(sprite_index = spr_male_right)
    {
        image_speed = 0.1;
        sprite_index = spr_male_idler 
    }
    //if sprite is facing left
    if(sprite_index = spr_male_left)
    {
        image_speed = 0.1;
        sprite_index = spr_male_idlel; 
    }
    
    This is the movement state
    Code:
    ///scr_move_state
    scr_get_input();
    spd=1;
    //if attacking
    if(attack_key)
    {
        state = scr_attack_state;
    }
    
    // go to idle state
    if (!down_key && !up_key && !left_key && !right_key) {
    state = scr_idle_state;
    }
    //if sprinting
    if(sprint_key)
    {
        state =scr_sprint_state;
    }
    //Move Down
    if (down_key) {
        phy_position_y += spd;
        sprite_index = spr_player;
        image_speed = .3;
    }
    //Move Up
    if (up_key) {
        phy_position_y -= spd;
        sprite_index = spr_male_up;
        image_speed = .3;
    }
    //Move Left
    if (left_key) {
        phy_position_x -= spd;
        sprite_index = spr_male_left;
        image_speed = .2;
    }
    //Move Right
    if (right_key) {
        phy_position_x += spd;
        sprite_index = spr_male_right;
        image_speed = .2;
    }
    
    Also when leaving the attack state to idle the sprite remains the attack sprite until I move the player.

    Finally here is the attack state code
    Code:
    scr_get_input();
    spd =0.05
    //if not attacking
    if(!attack_key)
    {
        state = scr_idle_state;
    }
    //if sprite is facing down
    if(sprite_index = spr_player)
    {
        sprite_index = spr_male_attackd;
        image_speed = .2;
    }
    //if sprite is facing up
    if(sprite_index = spr_male_up)
    {
        sprite_index = spr_player_attacku;
        image_speed = .2;
    }
    //if sprite is facing right
    if(sprite_index = spr_male_right)
    {
        sprite_index = spr_male_attackr;
        image_speed = .2;
    }
    //if sprite is facing left
    if(sprite_index = spr_male_left)
    {
        sprite_index = spr_male_attackl;
        image_speed = .2;
    }
    
    //Move Down
    if (down_key)
    {
        phy_position_y += spd;
        sprite_index = spr_male_attackd;
        image_speed = .2;
    }
    //Move Up
    if (up_key)
    {
        phy_position_y -= spd;
        sprite_index = spr_player_attacku;
        image_speed = .2;
    }
    //Move Left
    if (left_key)
    {
        phy_position_x -= spd;
        sprite_index = spr_male_attackl;
        image_speed = .2;
    }
    //Move Right
    if (right_key)
    {
        phy_position_x += spd;
        sprite_index = spr_male_attackr;
        image_speed = .2;
    }
    All that's in my create event for now with regards to the states is just setting the variable state to the idle state and my step event looks like this;
    Code:
    script_execute(state);
    Thanks for any help in advance.
     
  2. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    817
    Without getting too into your code, it looks like pressing attack takes you to the attack state.
    BUT, not pressing any key takes you back to the idle state.
    So you're in the attack state for a frame.
    I would use an animation end event (under other) and check my state or sprite. Ex:
    Code:
    // Animation end event
    if (state == en_states.attack)
    {
        state = en_states.idle;
    }
    The attack state, at least for me, would be where a sprite plays out and a hitbox is created. At the end of the animation, the player returns to idle or to previous state.
     
  3. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,991
    The sprite doesn't change back to the idle sprite because you handle the sprite changes in the idle state itself. Sprite changes should happen the moment you change the state, not after it. What's worse, in your idle state you only tell it to change to the idle sprite if you're already in the moving sprite; it says nothing about changing from the attacking sprite to the idle sprite.

    Also, your conditional tree is pretty convoluted just for changing sprites. You have a series of "if sprite_index==" checks just for the sake of changing the sprite. You should streamline this. Most people create a variable, like facing, which has a value from 0 to 3, and then use that to determine what sprite to use. My personal method is to put all the sprites in one or more arrays, like so:
    Code:
    idle_sprite[0] = spr_idle_right;
    idle_sprite[1] = spr_idle_up;
    idle_sprite[2] = spr_idle_left;
    idle_sprite[3] = spr_idle_down;
    Then to change the sprite, you just pass your facing variable as the array index, like so:
    Code:
    sprite_index = idle_sprite[facing];
    So...
    1. Make your attack state end after an elapsed amount of time or the sprite has finished animating, not based on any key presses or lack thereof.
    2. Change sprites at the same time you change state.
    3. Streamline your sprite changing conditional, preferable to an array.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice