• 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 Ladder problem



Trying to throw a ladder in my game but I'm having some problems. Right now, the player attaches himself to the ladder fine, switches to a "climb state" and moves up and down the ladder without a problem. He'll drop or jump from the ladder as well based on a keypress. However, when he climbs down the ladder and hits the ground, he switches back to the "move state", but he seems to get stuck about 4 pixels or so in the ground. Obviously, I'd prefer him not to get stuck. This is what I got so far...

hspd = 0;
vspd = 2;
grav = 0;

var inst;
inst = instance_place(x,y,obj_ladder);

//Centers player on the ladder
    other.x = x;

//climb = "w" key
if (climb){
    y -= vspd;
    image_speed = 1;
//climb_down = "s" key
}else if (climb_down){
    //If he hits the ground
    if (place_meeting(x, y+1, obj_solid)){
        //no longer climbing
        climbing = false;
        show_debug_message("hit ground");   
        //Don't think I need this line
        //sprite_index = spr_hero_jump;
        //Tried making him jump a bit to get out of the solid ground...that did not work at all
        //vspd = -4;
        //grav = 1;
        //switch back to basic move state
        state = move_state;
    //If he hasn't hit the ground
        y += vspd;
        image_speed = 1;

//up = "space_key"
}else if (up){
    //back to move state and fall off ladder
    state = move_state;

//if not moving on ladder
    image_speed = 0;   

Simon Gust

Might be because precision.
if (place_meeting(x, y+1, obj_solid)){
can be
if (place_meeting(x, y+vspd, obj_solid)){


^ I think that's likely it. As the code stands now, it basically says
"If there's nothing 1 pixel beneath me, go ahead and move down many pixels"
which practically guarantees going too far.

All in all, you want to avoid this kind of implementation when possible, for precisely this sort of reason; it's common to start out making collision checks and then moving based on the results, but things fall apart quickly whenever you add an extra "move" or "collision" mechanic to the game (especially vertical moving platforms, ladders, and enemies that push you backwards).

Whenever possible, try to take movement code and "other things pushing me around" code all together, and use them to compute an "intended x movement" and an "intended y movement." Then, after everything has had a say, do the movement.

Many attempts at platforming do everything all out of order by computing the intended movement result of something like a key press, and checking for a collision, and moving based on the key press...then moving on to the next logic check.

This seems to work in simple examples, but fails once you start building a game because the computer can only execute one piece at a time. Game code often wants to check movement based on key press, collision with solids, collision with ladders, collision with moving platforms, collision with enemies... All of these things might affect the player's movement. And if each check "moves" the player, then your poor player gets bounced around in many directions in a single game-step by each thing that wants to affect him/her. The result is that collision checks get missed, since your player might already have gotten moved by some other check a few lines earlier.

Simple example: If your player is going to hit the ceiling in one pixel, then don't go upward by 1 pixel. Now, since your player isn't hitting anything, and the "double jump" button is pressed...it's ok to move upwards, right? wrong :D
Better to say "player would go up by this amount based on their speed and gravity....and since double jump is pressed, they'd get this extra speed.... Then, after all the potential upward movement is added together, check how much movement is allowed and move."

Commonly, you'd have something like an End Step event, where you toss a while loop in there...
h = abs(h_move);
     if(!place_meeting(x+sign(h_move), y, obj_solid){
// Repeat for vertical movement
The above is a simplified example; you might have jump-through platforms to check, or physics to alter and so on.
But the idea in such an implementation is that all intended movement is figured out, and then, after everything has acted, the object proceeds 1 pixel at a time in each direction until it hits something impassible or until the movement is satisfied