GameMaker Undertale like movement in GMS: 2

P

Poptart

Guest
Hi,

I am fairly new to GameMaker, so if you wouldn't mind simplifying things, that would be awesome! Please let me know if I need to explain this better....

I was recently playing around with objects and getting a character to simply move when I came across an issue. I am using a very simple system to move in my player's step event. Here's an example:

if keyboard_check(vk_right) {
x += 2
sprite_index = spr_player_walk_right;
image_speed = 1;

This pattern for input continues through the three other arrow keys.
My issue is that if you press the right arrow key (or left) my player goes right (or left). If you continue holding the right arrow key(or left) and press the down or up arrow key my player's sprite changes to his up or down sprite. If you press the down or up key followed by the left or right arrow key, the sprite will not change to the right or left sprite, but stay on the up or down sprite.

I would like my player to be able to move like frisk in Undertale. In Undertale the first key you press displays the sprite connected to that key. If you press another key that would make your character move diagonally, the sprite from the first key press stays the same.

IE: You boot up Undertale and your player loads. you press the right key and your player starts moving right. Your player's sprite mapped to the right key animates. You then continue holding the right key and press the down key. Your player's sprite does not change, but your player moves diagonally across the screen. This also applies to pressing down/up key first and the right/left key second.

Any help would be greatly appreciated. Thanks! :)
 

flerpyderp

Member
You could have the sprite only change on horizontal movement input if there isn't currently vertical movement input, and vice versa. So, in the checks for left and right keys, before changing the sprite index, first check that there is no input from the up or down keys.
 

mimusic

Member
Simplest way I can think of is only allowing the sprite to change when a keypress wasn't previously registered. You could set up a boolean that tells the game whether or not any of the directional keys is already being pressed, and use that to allow or deny the game to change sprites

Code:
if ( keyboard_check( vk_right ) ) {
    x += 2;
    if ( ! arrowInput ) {
        sprite_index = spr_player_walk_right;
    }
    image_speed = 1;
}

arrowInput = (keyboard_check(vk_right) || keyboard_check(vk_left) || keyboard_check( yadda yadda, you get the point) );
'arrowInput' is a variable (user-defined, so make sure to declare it in the create event) that checks if ANY of the direction keys is being pressed, and will only be false when none of them are pressed. Make sure that arrowInput is updated after the sprite-changing code, since we want that variable to allow a single step in which sprites can still be changed. While any of those keys is pressed, arrowInput remains true, and will only go back to false (thus allowing a sprite change again) when none of them are pressed.
 
P

Poptart

Guest
Sorry, I am having trouble still (I really am a noob) how would I go about Making sure that arrowInput is updated after the sprite-changing code, since we want that variable to allow a single step in which sprites can still be changed. While any of those keys is pressed, arrowInput remains true, and will only go back to false (thus allowing a sprite change again) when none of them are pressed?
 

flerpyderp

Member
While any of those keys is pressed, arrowInput remains true, and will only go back to false (thus allowing a sprite change again) when none of them are pressed?
This would be the case if the "arrowInput = etc " line was placed before the rest of the code in that example. But notice how arrowInput only becomes true after the key checking code. When the key is first held, arrowInput is still false and therefore the sprite changes. Then after that, the arrowInput line is reached, changing it to true.

The problem with the code in that example though is that it would be possible to have the "up" sprite displayed while moving down, "left" sprite while moving right etc. because any direction key being held will disable the sprite change. If this is unwanted, I would simply change it to have separate checks for "up/down" and "left/right".
 
Last edited:
P

Poptart

Guest
This would be the case if the "arrowInput = etc " line was placed before the rest of the code in that example. But notice how arrowInput only becomes true after the key checking code. When the key is first held, arrowInput is still false and therefore the sprite changes. Then after that, the arrowInput line is reached, changing it to true.
The problem with the code in that example though is that it would be possible to have the "up" sprite displayed while moving down, "left" sprite while moving right etc. because any direction key being held will disable the sprite change. If this is unwanted, I would simply change it to have separate checks for "up/down" and "left/right".
could you give me a working example?
 

mimusic

Member
could you give me a working example?
The code I gave you is a working example, you just need to expand it to suit all 4 of your directions. The code I shared already has arrowInput in the correct placement, I said what I said mainly to caution against putting arrowInput at the beginning of the step, which would result in incorrect behavior.

This is the order of things
  1. At creation, arrowInput is set to false
  2. When a direction key is pressed, if arrowInput is false, change the sprite.
  3. When a direction key is pressed, set arrowInput to true; otherwise, set arrowInput to false
  4. Go back to step 2
Step 2 (possible sprite change) always runs before step 3 (arrowInput update), meaning that for a single step, there exists a case where a key is pressed BUT arrowInput is false when checking to update the sprite, because we perform the update after checking to update the sprite. My explanation feels a bit weak, so sorry if this doesn't help it make any more sense. If I can think of a better explanation, I'll edit it into this comment. Currently trying to think of an effective metaphor for the situation, since I find those tend to help me visualize concepts better than direct explanations do.
 
P

Poptart

Guest
Okay. I was having trouble implementing your suggestions, but I did solve it by adding new scripts per each arrow key. I created another boolean which determines whether or not set key is pressed. I set the variable to false when it is pressed in another function!

Thank you very much and if anyone else has any other suggestions I would be happy to hear them!!!
 

Bentley

Member
I would like my player to be able to move like frisk in Undertale. In Undertale the first key you press displays the sprite connected to that key.
Yes, I had this problem. I don't know all that much about how image_speed works, but I think it increments. So if you're not holding the right key long enough, you won't cycle to the next frame of animation.

Pseudo Code:
Code:
if (right_key)
{
    sprite_index = spr_player_right;
    image_speed = 1;
}
else
{
    image_index = 0.99; // Set image index to the 1st frame, but very close to the 2nd
    image_speed = 0; // and stop animating
}
Your image index is now 0.99, so one key press is going to set your image index in the 1's, and you'll see the next frame.
 
P

Poptart

Guest
Yes, I had this problem. I don't know all that much about how image_speed works, but I think it increments. So if you're not holding the right key long enough, you won't cycle to the next frame of animation.

Pseudo Code:
Code:
if (right_key)
{
    sprite_index = spr_player_right;
    image_speed = 1;
}
else
{
    image_index = 0.99; // Set image index to the 1st frame, but very close to the 2nd
    image_speed = 0; // and stop animating
}
Your image index is now 0.99, so one key press is going to set your image index in the 1's, and you'll see the next frame.

Very helpful! thank you!
 
Top