GML Slopes and Platformer Movement for Beginners

JeanSwamp

Member
@Bentley I'm playing around a bit with this, trying to set an acel/dec with down/up slopes, but seems quite hard the way the scripts work, and I'm not a fan of your suggestion of creating some sort of climb power based on dy.

Any suggestions?
 

Bentley

Member
@Bentley I'm playing around a bit with this, trying to set an acel/dec with down/up slopes, but seems quite hard the way the scripts work, and I'm not a fan of your suggestion of creating some sort of climb power based on dy.

Any suggestions?
Hey Jean, I had something a while ago when I was working on a Kirby's Adventure clone (I use the word "clone" very loosely). Basically, if he was going uphill, I would get the direction from Kirby's feet to the slope. I'd then use lengthdir_x(hspd, dir_of_slope) and move the player that distance. So his speed is decreased uphill.

This tutorial was specifically for slopes on destroyable terrain. If your slopes are pre-defined (you have sprites for slopes that aren't created in-game), you can just get the direction by looking at the slope. For example, if the sprite is a diagonal at 45 degrees, you'd input that:

// Pseudo code
hspd = lengthdir_x(hspd_max, 45);

You do the opposite downhill. I'll elaborate / write some code if you reply.
 
Last edited:
Hey Jean, I had something a while ago when I was working on a Kirby's Adventure clone (I use the word "clone" very loosely). Basically, if he was going uphill, I would get the direction from Kirby's feet to the slope. I'd then use lengthdir_x(hspd, dir_of_slope) and move the player that distance. So his speed is decreased uphill.

This tutorial was specifically for slopes on destroyable terrain. If your slopes are pre-defined (you have sprites for slopes that aren't created in-game), you can just get the direction by looking at the slope. For example, if the sprite is a diagonal at 45 degrees, you'd input that:

// Pseudo code
hspd = lengthdir_x(hspd_max, 45);

You do the opposite downhill. I'll elaborate / write some code if you reply.
I felt the need to post just to say how simple yet brilliant this is.
 

JeanSwamp

Member
Hey Jean, I had something a while ago when I was working on a Kirby's Adventure clone (I use the word "clone" very loosely). Basically, if he was going uphill, I would get the direction from Kirby's feet to the slope. I'd then use lengthdir_x(hspd, dir_of_slope) and move the player that distance. So his speed is decreased uphill.

This tutorial was specifically for slopes on destroyable terrain. If your slopes are pre-defined (you have sprites for slopes that aren't created in-game), you can just get the direction by looking at the slope. For example, if the sprite is a diagonal at 45 degrees, you'd input that:

// Pseudo code
hspd = lengthdir_x(hspd_max, 45);

You do the opposite downhill. I'll elaborate / write some code if you reply.
I calculate the angle of the slope I'm about to collide to set the sprite rotation accordingly, so I guess is similar approach to your lengthdir_x(hspd, dir_of_slope) concept. I only move forward as I'm using this for some sort of minecart mini game.

When you say, do the opposite for downhill, what do you mean? Can't really figure it out
 

Bentley

Member
@JeanSwamp You could move at hspd_max and add additional movement based on the slope
Code:
hspd_extra = hspd_max - lengthdir_x(hspd_max, 45);
hspd += hspd_extra;
Something like that. You just find out how much hspd you didn't move b/c of the slope and add that to your current speed.

Edit: and obviously this doesn't account for what you need to do when you are floating above the slope. I'd just use a while loop and move him to the ground.
 
Last edited:

SoMalFra

Member
Hey, so I'm really sorry for necroposting on this thread but you know, there is always hope!
I was using this code for a simple platformer, however I've come into a bug. If the player is touching a wall and facing it, when he jumps and look to the other side, two things can happen: 1:The player totally stop moving up and just fall, like the jump speed didn't matter, or 2:, It can just get stuck in the wall. It's not a problem with collision mask nor the sprite origin. If you can help me, I'd really appreciate.
Again, sorry for bothering and necroposting.
It has already happened in this threat and you answered, so I guess ir's no harm trying.
Thank you for the help, though!
 

Bentley

Member
@SoMalFra Hey, I'm happy to try and help. My first thought would be a mask but you said that it's not that. Just to double check, when the sprite changes is the same collision masked used with the same origin? I ask because if it's slightly wider, you'll get stuck/weird things will happen. You could use a few "show_message" calls when you're in the circumstance you described to see if a collision is occurring when it shouldn't be. If that doesn't work, let me know.
 

Schtipadoo

Member
Yo!

ive been looking for this, and i got some questions, it might be too late to ask this
but since this is the only helpful solution that actually worked for what im doing currently

i was trying to get slopes to work with momentum and such, as far as i got i manage to slow down the player with the angle of the slope (in my case in the angle of the player)

is there anyway i can make the same effect for going down a slope but make the player faster, and also automatically sliding the player down the slope depending how steep it is?

i havent figured out how to do so

and im almost giving up on my project because of this
(i was trying to make a 2d skating game)

heres the step event of the player


GML:
var kright, kleft, kjump, xdir, onground, kjump;

kright   = keyboard_check(vk_right);
kleft    = keyboard_check(vk_left);
kdown    = keyboard_check(vk_down);
kjump    = keyboard_check_pressed(vk_up);
xdir     = keyboard_check(vk_right) - keyboard_check(vk_left);
onground = place_meeting(x, y + 1, obj_wall);

//check if on ground
if( place_free( x, y+1 )){
   vspd += grav;
}
if kjump{
    vspd = -vspd_max
}

//set horizontal movement based on controls
if kright
{
    hspd = lerp(hspd,lengthdir_x(hspd_max,angle+30),0.25); // does not work if +30 is added
}
if kleft
{
    hspd = lerp(hspd,lengthdir_x(-hspd_max,angle-30),0.25); // goes faster if going to the other side witouth -30
}
if !kright && !kleft && !kdown
{
    hspd = lerp(hspd,0,0.1); // worlds most basic friction
}


//Find p1
for (i=0;i<=sprite_width;i+=1){
    if position_meeting(bbox_left,bbox_bottom+i,obj_wall){
        p1=i;
        break;
    }
}

//Find p2
for (i=0;i<=sprite_width;i+=1){
    if position_meeting(bbox_right,bbox_bottom+i,obj_wall){
        p2=i;
        break;
    }
}
//Now, rotate the sprite!
angle = point_direction(bbox_left,bbox_bottom+p1,bbox_right,bbox_bottom+p2);
angle = round(angle);

// Actually move
var dy;
repeat (abs(hspd)) // Horizontal movement
{
   if (onground) // Check for slopes if we are on the ground
   {
        if (place_meeting(x + sign(hspd), y, obj_wall)) // Up slope
        {
            dy = up_slope();     // Measure the slope
            if (dy <= slope_max) // Climbable
            {
                x += sign(hspd);
                y -= dy;
                continue;
            }
            hspd = 0; // Unclimbable
            break;
        }
        else if (!place_meeting(x + sign(hspd), y + 1, obj_wall)) // Down slope (just like we did up slopes)
        {
            dy = down_slope();       
            if (dy <= slope_max)
            {
                x += sign(hspd);
                y += dy;
                continue;
            }
            x += sign(hspd); // Continue the loop rather than break the loop to keep momentum
            continue;
        }
        else x += sign(hspd); // Flat
    }
    else // We're in the air so we don't check for slopes
    {
        if (!place_meeting(x + sign(hspd), y, obj_wall)) x += sign(hspd);
        else
        {
            hspd = 0;
            break;
        }
    }
}
repeat (abs(vspd)) // Vertical movement
{
    if (!place_meeting(x, y + sign(vspd), obj_wall)) y += sign(vspd);
    else
    {
        vspd = 0;
        break;
    }
}
 

Bentley

Member
@Schtipadoo I'm sorry to hear you may be giving up on your project. Here's one idea:
GML:
var angle = 315;
var hspd_extra = hspd - lengthdir_x(hspd, angle);
var hspd_total = hspd + hspd_extra;

repeat (abs(hspd_total))
The idea is that the steeper the angle, the larger hspd_extra should be. You then add that to your current speed. If the angle were 300, hspd_total would be more b/c 300 is steeper than 315.
 
Last edited:
Top