game-makergmlgame-maker-languagegame-maker-studio-1.4

Player sticks in a wall while moving on slope up


I made a simple slope movement in my GameMaker game.

Everything works fine except if player goes up slope and its speed is high enough not to have time to react to the collision code it gets stuck in the wall.

This is how it looks: GIF.

So my code looks like this:

Create Event:

hspd = 0;
vspd = 0;

grav = 2;

Step Event:

// Movement
if (keyboard_check(vk_right) && !keyboard_check(vk_left)) {
    hspd = 9;
} else
if (keyboard_check(vk_left) && !keyboard_check(vk_right)) {
    hspd = -9;
}

// Check not moving
if ((!keyboard_check(vk_right) && !keyboard_check(vk_left)) || (keyboard_check(vk_right) && keyboard_check(vk_left))) {
    hspd = 0;
}

// Gravity
if (!place_meeting(x, y+1, parent_ground)) {
    vspd += grav;
}

// Jumping
if (place_meeting(x, y+1, parent_ground)) {
    if (keyboard_check_pressed(vk_up)) {
        vspd = -20;
    }
}

// Variables
var hspd_final = hspd;

// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, horizontal_collision)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        // Declare yplus
        yplus = 0;

        // Loop
        while (place_meeting(x+hspd_final, y-yplus, parent_ground) && yplus <= abs(1*hspd_final)) {
            yplus += 1;
        }
        y -= yplus;
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}

// Down slope
down_slope = instance_place(x, y+1, parent_ground);
if (down_slope != noone && down_slope.object_index != object_ground) {
    if (place_meeting(x, y+1, parent_ground)) {
        yminus = abs(hspd_final);

        while (place_meeting(x+hspd_final, y+yminus, parent_ground) && yminus != 0) {
            yminus --;
        }

        y += yminus;
    }
}

// Initialize horizontal speed
x += hspd_final;

// Vertical collision
if (place_meeting(x, y+vspd, parent_ground)) {
    while (!place_meeting(x, y+sign(vspd), parent_ground)) {
        y += sign(vspd);
    }
    vspd = 0;
}

// Initialize vertical speed
y += vspd;

I have 3 wall objects: object_ground (basic block), object_slope (percise slope object) and parent_ground (object which child objects are object_ground and object_slope).

Thank you.


Solution

  • A simple and proper solution to fix this nicely, is check the positions in between. Instead of moving it spd pixels at once, move it 1 pixel spd times. If in the mean time you encounter a collision, you've hit the max.

    This way it doesn't matter if you move with 0.01 speed or with 9999.0 speed.