• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

[Solved] Player get stuck when go up slopes straight to wall.

E

Edwin

Guest
Hey, it's me, Edwin again. yey

So basically a weird problem that I have is when player goes up via slope, and then right after it player collide with the wall, player get stuck.

It looks like this:



This is my Step Event code:
Code:
/// 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;
    }
}

// Jump cancel
if (vspd < 0) {
    if (keyboard_check_released(vk_up)) {
        vspd *= 0.4;
    }
}

// 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 think some variables like hspd, vspd aren't really matter here so you can declare them by yourself. But objects like parent_ground, object_ground, object_slope are more important:
  • parent_ground is a parent object which childs are object_ground and object_slope;
  • object_ground is a simple block object as basically in other infinite amount of games.
  • object_slope is a slope with built-in precise collision.
Thank you for the help.
 

jo-thijs

Member
Hey, it's me, Edwin again. yey

So basically a weird problem that I have is when player goes up via slope, and then right after it player collide with the wall, player get stuck.

It looks like this:



This is my Step Event code:
Code:
/// 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;
    }
}

// Jump cancel
if (vspd < 0) {
    if (keyboard_check_released(vk_up)) {
        vspd *= 0.4;
    }
}

// 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 think some variables like hspd, vspd aren't really matter here so you can declare them by yourself. But objects like parent_ground, object_ground, object_slope are more important:
  • parent_ground is a parent object which childs are object_ground and object_slope;
  • object_ground is a simple block object as basically in other infinite amount of games.
  • object_slope is a slope with built-in precise collision.
Thank you for the help.
You only use this code:
Code:
        while (place_meeting(x+hspd_final, y-yplus, parent_ground) && yplus <= abs(1*hspd_final)) {
            yplus += 1;
        }
        y -= yplus;
when no collision with a ground instance has been detected, so slopes are ignored in collisions with ground instances.
If you change parent_ground to object_slope in this code, you can apply it to both collision responses and solve (at least partially) the issue you're having.
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
   
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
   
    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 {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}
EDIT: Fixed a mistake in my code above.
 
Last edited:
E

Edwin

Guest
You only use this code:
Code:
        while (place_meeting(x+hspd_final, y-yplus, parent_ground) && yplus <= abs(1*hspd_final)) {
            yplus += 1;
        }
        y -= yplus;
when no collision with a ground instance has been detected, so slopes are ignored in collisions with ground instances.
If you change parent_ground to object_slope in this code, you can apply it to both collision responses and solve (at least partially) the issue you're having.
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    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 {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}
EDIT: Fixed a mistake in my code above.
Hm. Now my game simply freezes after that multi collision. And my player jumps if he collides with object_ground without being on a slope. Well, nevertheless thank you, yet you already helped me.
 
E

Edwin

Guest
Maybe after 500+ years someone will fix this, but now the problem is not so terrible, you know.
 

jo-thijs

Member
Hm. Now my game simply freezes after that multi collision. And my player jumps if he collides with object_ground without being on a slope. Well, nevertheless thank you, yet you already helped me.
You're right. An oversight of me.

The easiest fix is to put a limit on the amount of pixels the player can horizontally move towards a ground instance:
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, horizontal_collision) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}
Maybe after 500+ years someone will fix this, but now the problem is not so terrible, you know.
I'm not sure what you're trying to say here.
 
E

Edwin

Guest
You're right. An oversight of me.

The easiest fix is to put a limit on the amount of pixels the player can horizontally move towards a ground instance:
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, horizontal_collision) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}

I'm not sure what you're trying to say here.
Now when I collide a wall player goes through it.
 

jo-thijs

Member
Now when I collide a wall player goes through it.
My bad, in the while loop:
Code:
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
I meant to write object_slope, rather than object_ground.

EDIT:
And you'll probably also want to change horizontal_collision to parent_ground in this line:
Code:
        while (!place_meeting(x+sign(hspd_final), y, horizontal_collision) && abs(x - xprevious) < abs(hspd_final)) {
 
Last edited:
E

Edwin

Guest
My bad, in the while loop:
Code:
    while (place_meeting(x+hspd_final, y-yplus, object_ground) && yplus <= abs(1*hspd_final)) {
I meant to write object_slope, rather than object_ground.

EDIT:
And you'll probably also want to change horizontal_collision to parent_ground in this line:
Code:
        while (!place_meeting(x+sign(hspd_final), y, horizontal_collision) && abs(x - xprevious) < abs(hspd_final)) {
Looks like, to get stuck in the wall, I don't even need acceleration anymore.


But anyway thank you that you do care. Maybe game just can't handle multiple collisions occurring at the same time.
 

jo-thijs

Member
Looks like, to get stuck in the wall, I don't even need acceleration anymore.


But anyway thank you that you do care. Maybe game just can't handle multiple collisions occurring at the same time.
What do you mean with acceleration?
The player doesn't have acceleration.

Anyway, I tested my last proposed solution and it works for me, I did not get stuck.
Can you confirm that you're using the code I suggested by uploading your current step event?
Is there some other relevant code in your project?
 
E

Edwin

Guest
What do you mean with acceleration?
The player doesn't have acceleration.

Anyway, I tested my last proposed solution and it works for me, I did not get stuck.
Can you confirm that you're using the code I suggested by uploading your current step event?
Is there some other relevant code in your project?
I added acceleration for hspd just for a test, guess that is the problem. In a collision if the speed is an odd value, the player stuck.
 
E

Edwin

Guest
This is my Step Event right now:
Code:
/// Step Event

// Movement
if (keyboard_check(vk_right) && !keyboard_check(vk_left)) {
    hspd = 7; // 7 divide 2 is 3.5 so the game is kinda difficult to calculate subpixels, i guess
} else
if (keyboard_check(vk_left) && !keyboard_check(vk_right)) {
    hspd = -7;
}

// 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;
    }
}

// Jump cancel
if (vspd < 0) {
    if (keyboard_check_released(vk_up)) {
        vspd *= 0.4;
    }
}

// Variables
var hspd_final = hspd;

// Horizontal collision
var horizontal_collision = instance_place(x+hspd_final, y, parent_ground);

if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
    // Loop
    if (horizontal_collision.object_index != object_ground) {
        while (place_meeting(x+hspd_final, y-yplus, parent_ground) && yplus <= abs(1*hspd_final)) {
            yplus += 1;
        }
    }
    y -= yplus;
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, object_ground) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        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;
You can see my hspd is 7 (odd value). It does work if hspd is for example 6 or any other even number.

Edit: by the way, I don't have object called object_slope because I have multiple of them (left side, right side, upside down etc) so I just use parent_ground instead of it.
 
Last edited:

jo-thijs

Member
This is my Step Event right now:
Code:
/// Step Event

// Movement
if (keyboard_check(vk_right) && !keyboard_check(vk_left)) {
    hspd = 7; // 7 divide 2 is 3.5 so the game is kinda difficult to calculate subpixels, i guess
} else
if (keyboard_check(vk_left) && !keyboard_check(vk_right)) {
    hspd = -7;
}

// 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;
    }
}

// Jump cancel
if (vspd < 0) {
    if (keyboard_check_released(vk_up)) {
        vspd *= 0.4;
    }
}

// Variables
var hspd_final = hspd;

// Horizontal collision
var horizontal_collision = instance_place(x+hspd_final, y, parent_ground);

if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
    // Loop
    if (horizontal_collision.object_index != object_ground) {
        while (place_meeting(x+hspd_final, y-yplus, parent_ground) && yplus <= abs(1*hspd_final)) {
            yplus += 1;
        }
    }
    y -= yplus;
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, object_ground) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        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;
You can see my hspd is 7 (odd value). It does work if hspd is for example 6 or any other even number. I can siimply round my current hspd, I guess.

Edit: by the way, I don't have object called object_slope because I have multiple of them (left side, right side, upside down etc) so I just use parent_ground instead of it.
There are 3 differences with what I suggested:
1) You have an additional if-statement around the slope loop:
Code:
    // Loop
    if (horizontal_collision.object_index != object_ground) {
        ...
    }
2) In the slope loop, you check for parent_ground instead of object_slope.
3) In the ground loop, you check for object_ground, rather than parent_ground.

Try this instead:
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_slope) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, parent_ground) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}
 
E

Edwin

Guest
There are 3 differences with what I suggested:
1) You have an additional if-statement around the slope loop:
Code:
    // Loop
    if (horizontal_collision.object_index != object_ground) {
        ...
    }
2) In the slope loop, you check for parent_ground instead of object_slope.
3) In the ground loop, you check for object_ground, rather than parent_ground.

Try this instead:
Code:
// Horizontal collision
horizontal_collision = instance_place(x+hspd_final, y, parent_ground);
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, object_slope) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    if (horizontal_collision.object_index == object_ground) {
        while (!place_meeting(x+sign(hspd_final), y, parent_ground) && abs(x - xprevious) < abs(hspd_final)) {
            x += sign(hspd_final);
        }
        hspd_final = 0;
    } else {
        while (place_meeting(x, y+1, parent_ground)) {
            y -= 1;
        }
    }
}
I don't have object called object_slope. They are multiple: object_slope1, object_slope2, etc. What should I do?
 

jo-thijs

Member
I don't have object called object_slope. They are multiple: object_slope1, object_slope2, etc. What should I do?
Ah, I thought you had an object called object_slope because of:
object_slope is a slope with built-in precise collision.
No problem though, create a parent object parent_slope that is the parent of each slope object and use that instead of object_slope.
Also make sure to make parent_ground the parent of parent_slope.
 
E

Edwin

Guest
Ah, I thought you had an object called object_slope because of:

No problem though, create a parent object parent_slope that is the parent of each slope object and use that instead of object_slope.
Also make sure to make parent_ground the parent of parent_slope.
Still does not work correctly. if you have time for it, I could share you my project: Google Drive. Please I am probably just doing something wrong, but you can find out exactly what in details if you want. Thanks.
 

jo-thijs

Member
Still does not work correctly. if you have time for it, I could share you my project: Google Drive. Please I am probably just doing something wrong, but you can find out exactly what in details if you want. Thanks.
It's fixed if you don't make a distinction between what you're colliding with:
Code:
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, parent_slope) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    while (!place_meeting(x+sign(hspd_final), y, parent_ground) && abs(x - xprevious) < abs(hspd_final)) {
        x += sign(hspd_final);
    }
    hspd_final = 0;
}
 
E

Edwin

Guest
It's fixed if you don't make a distinction between what you're colliding with:
Code:
if (horizontal_collision != noone) {
    // Declare yplus
    yplus = 0;
 
    // Loop
    while (place_meeting(x+hspd_final, y-yplus, parent_slope) && yplus <= abs(1*hspd_final)) {
        yplus += 1;
    }
    y -= yplus;
 
    while (!place_meeting(x+sign(hspd_final), y, parent_ground) && abs(x - xprevious) < abs(hspd_final)) {
        x += sign(hspd_final);
    }
    hspd_final = 0;
}
Yes, it worked! Thank you! :)
 
N

NeZvers

Guest
Each time you call place_meeting/ instance_place/ etc. all the instances of the object you are checking against are doing checks if they are in a position to collide. Now in that while loop each time it repeats it goes through all instances to check if you are colliding with any of them.
That's why superior collision system is so-called grid collision or if you have GMS2 then you have the option to do tile collision (Shoun Spalding have a tutorial on that). But if you are new to programming or to Gamemaker it's ok to use this "traditional" collision, because many published GM games have done it, although keep in mind you can save much with better collision.
 
Top