Player Walking...

E

Explosive Photons

Guest
I am creating an RPG in the style of the Mother Games and Undertale. I have created separate sprites for my overworld character. One going up, One going down, One going left and One going right. Each contains to images that create a sort of animation. I have programmed it so when you press the left button, it switches the sprite to the left facing one, changes the image speed to 0.2 and using drag and drop moves the player towards -8 y (relative). When you release left, the image_index goes back to 0 and the image speed goes to 0 too. I have used this same idea for all directions and it works well. However, when I try to walk in two directions at once, the player stops. I know this is to do with my programming, so has anyone got any suggestions about how I could program this?
 

matharoo

Tutorial Guy
YYG Staff
You can use this simple code in the Step event:
Code:
if (keyboard_check(vk_left)) x -= 8;
else
if (keyboard_check(vk_right)) x+= 8;

if (keyboard_check(vk_up)) y -= 8;
else
if (keyboard_check(vk_down)) y+= 8;
It will allow for your player to walk diagonally (both horizontal and vertical directions).
 
E

eidobunny

Guest
I am creating an RPG in the style of the Mother Games and Undertale. I have created separate sprites for my overworld character. One going up, One going down, One going left and One going right. Each contains to images that create a sort of animation. I have programmed it so when you press the left button, it switches the sprite to the left facing one, changes the image speed to 0.2 and using drag and drop moves the player towards -8 y (relative). When you release left, the image_index goes back to 0 and the image speed goes to 0 too. I have used this same idea for all directions and it works well. However, when I try to walk in two directions at once, the player stops. I know this is to do with my programming, so has anyone got any suggestions about how I could program this?
Hello, it just so happens that I'm working on a game heavily inspired by Undertale. I recreated the Undertale movement system to start out, and I don't mind sharing my work. It's a bit complicated because there are some subtleties that aren't immediately obvious as you're playing.

Feel free to use the code or adapt it to your own needs. The only thing I need to add to my code is directional idle sprites, but it should be fairly simple to implement if you understand the rest of the code. Right now I just have one generic idle sprite.

It should be noted that I don't use any DnD, only GML. The first two code blocks are code actions in their respective events. The last 3 are scripts.

Code:
///PLAYER OBJECT CREATE EVENT

//Maximum speed
spd = 4;

//Current movement speed
hspd = 0;
vspd = 0;

//Initialize basic properties
sprite_index = spr_testidle;
image_speed = 0.5;

//Initialize basic movement state
state = move_state;

/*

Directions for top-down spritework.

0 = down
1 = left
2 = up
3 = right

*/

dir = 0;
Code:
///PLAYER OBJECT STEP EVENT

//Get input (keyboard/controller)
get_input();

//Execute the state (in the basic case, this calls the move_state script)
script_execute(state);
Code:
///get_input()

left = keyboard_check(vk_left);
right = keyboard_check(vk_right);
up = keyboard_check(vk_up);
down = keyboard_check(vk_down);
Code:
///move_state

//Set animation speed for movement

image_speed = 1;

//Set default speed if there is no input

hspd = 0;
vspd = 0;

//Set speed to the direction you are pressing as long as there isn't a wall there
//Left and up take precedence

if(right && !place_meeting(x+1,y,Solid)) hspd = spd;

if(left && !place_meeting(x-1,y,Solid)) hspd = -spd;

if(down && !place_meeting(x,y+1,Solid)) vspd = spd;

if(up && !place_meeting(x,y-1,Solid)) vspd = -spd;

//Prevent stuttering if against a wall pressing opposite directional buttons

/*

SPECIAL NOTE: The following two lines of uncommented code deviate from Undertale.
In Undertale if you hold both UP & DOWN at the same time and run into a wall,
your character will stutter against it. Also if you hold LEFT & RIGHT and run into a wall,
your character will stop in its tracks. I fixed those issues in the next two lines of uncommented code.
if you truly wanted an exact replica of Undertale, replace them with this instead:

if(left && right && place_meeting(x-1,y,Solid))
{
hspd = 0;
vspd = 0;
}

This will replicate the stuttering effect and the freeze effect you encounter in Undertale.

*/

if(left && right && place_meeting(x-1,y,Solid)) hspd = 0;

if(up && down && place_meeting(x,y-1,Solid)) vspd = 0;

//Set the sprite to the appropriate direction

if(hspd < 0) sprite_index = spr_testleft;

if(hspd > 0) sprite_index = spr_testright;

if(vspd < 0) sprite_index = spr_testup;

if(vspd > 0) sprite_index = spr_testdown;

//Sprite direction correction in special cases of multiple button press combinations

if((right && down && left && !up) || (right && down && !left && !up && dir == 1) || (left && down && !right && !up && dir == 3)) dir = 0;

if((down && left && up && !right) || (down && left && !up && !right && dir == 2) || (up && left && !right && !down && dir == 0)) dir = 1;

if((left && up && right && !down) || (left && up && !right && !down && dir == 3) || (right && up && !down && !left && dir == 1)) dir = 2;

if((up && right && down && !left) || (up && right && !down && !left && dir == 0) || (down && right && !up && !left && dir == 2)) dir = 3;

//Maintain sprite momentum by checking the previous sprite direction

if(hspd < 0 && dir == 1 && left) sprite_index = spr_testleft;

if(hspd > 0 && dir == 3 && right) sprite_index = spr_testright;

if(vspd < 0 && dir = 2 && up) sprite_index = spr_testup;

if(vspd > 0 && dir = 0 && down) sprite_index = spr_testdown;

//Special checks when you're up against a wall trying to move against or along it

if(sprite_index == spr_testleft)
{
   if(place_meeting(x-1,y,Solid))
   {
       if(vspd > 0 && !place_meeting(x,y+1,Solid))
       {
           sprite_index = spr_testdown;
           dir = 3;
       }
       else if(vspd < 0 && !place_meeting(x,y-1,Solid))
       {
           sprite_index = spr_testup;
           dir = 1;
       }
       else
       {
           hspd = 0;
           vspd = 0;
       }
   }
   else dir = 1;
}

if(sprite_index == spr_testright)
{
   if(place_meeting(x+1,y,Solid))
   {
       if(vspd > 0 && !place_meeting(x,y+1,Solid))
       {
           sprite_index = spr_testdown;
           dir = 3;
       }
       else if(vspd < 0 && !place_meeting(x,y-1,Solid))
       {
           sprite_index = spr_testup;
           dir = 1;
       }
       else
       {
           hspd = 0;
           vspd = 0;
       }
   }
   else dir = 3;
}

if(sprite_index == spr_testup)
{
   if(place_meeting(x,y-1,Solid))
   {
       if(hspd > 0 && !place_meeting(x+1,y,Solid))
       {
           sprite_index = spr_testright;
           dir = 3;
       }
       else if(hspd < 0 && !place_meeting(x-1,y,Solid))
       {
           sprite_index = spr_testleft;
           dir = 1;
       }
       else
       {
           hspd = 0;
           vspd = 0;
       }
   }
   else dir = 2;
}

if(sprite_index == spr_testdown)
{
   if(place_meeting(x,y+1,Solid))
   {
       if(hspd > 0 && !place_meeting(x+1,y,Solid))
       {
           sprite_index = spr_testright;
           dir = 3;
       }
       else if(hspd < 0 && !place_meeting(x-1,y,Solid))
       {
           sprite_index = spr_testleft;
           dir = 1;
       }
       else
       {
           hspd = 0;
           vspd = 0;
       }
   }
   else dir = 0;
}

//If there is no input, default to the idle state

if(hspd == 0 && vspd == 0)
{
   sprite_index = spr_testidle;
   image_speed = 0.5;
}

//Actually move the player

move(Solid);
Code:
///move(collision_object)

var collision_object = argument0;

//Horizontal collisions

if(place_meeting(x+hspd,y,collision_object))
{
   while(!place_meeting(x+sign(hspd),y,collision_object))
   {
       x += sign(hspd);
   }
   hspd = 0;
}

x += hspd;

//Vertical collisions

if(place_meeting(x,y+vspd,collision_object))
{
   while(!place_meeting(x,y+sign(vspd),collision_object))
   {
       y += sign(vspd);
   }
   vspd = 0;
}

y += vspd;
Obviously just replace spr_testleft (and the others) with the appropriate sprite names. Use the "dir" variable to calculate the correct idle facing direction when writing idle sprite code.

Hope this helps! It might be a little above your skill level but keep working at it and keep trying to make great things! Good luck.
 
Last edited by a moderator:
E

Explosive Photons

Guest
Thanks! That will really help me. BTW are you good at art?
 
Top