0

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.

younyokel
  • 327
  • 2
  • 15

2 Answers2

2

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.

Rob
  • 4,927
  • 4
  • 26
  • 41
  • How exactly can I move my player `spd` times? Like `repeat (spd) { hspd += 1; }` and then clamp my `hspd`? – younyokel Jun 05 '19 at 10:59
  • Yes, or in a while / for loop. But looking at your code it actually looks like you're moving back the object if it is colliding (the while loop does that). What I think is happening though is that your "vertical movement" is pulling the player down after the slope code has ran. I usually use my own speed and direction variables, and then try to move smoothly, pixel by pixel, checking every one along the line. – Rob Jun 05 '19 at 11:05
0

This is quite a common problem with game-maker, and it only have 2 real solutions.

  1. Changing your room speed so it can keep up
  2. Reducing your player(white cube) speed
  • Well, my player speed is not an even value so I guess because of it, player get stuck inside the walls. I'd like to make my movement not linear so player will have acceleration and stuff, but it means the speed value will have odd number. How can I implement that? – younyokel May 31 '19 at 13:08