• 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!

GameMaker Issue with Collision and Movement [SOLVED]

Zabicka

Member
I'm using this Collision code:
Code:
// Horizontal
if (place_meeting(x + hspd, y, obj_wall)) {
    while (!place_meeting(x + sign(hspd), y, obj_wall)) {
        x += sign(hspd);
    }
    hspd = 0;
}
x += hspd;

// Vertical
if (place_meeting(x, y + vspd, obj_wall)) {
    while (!place_meeting(x, y + sign(vspd), obj_wall)) {
        y += sign(vspd);
    }
    vspd = 0;
}
y += vspd;
When my character is going diagonally and touching the wall
he moves slower than just touching the wall and moving horizontally, how can I fix this?
 
J

Jonar

Guest
When you say moving slower is that both horizontally and vertically or just one of those?
 

Zabicka

Member
When you say moving slower is that both horizontally and vertically or just one of those?
When moving only horizontally, or only verticaly and touching the wall everything is moving fine, but when moving horizontally and vertically at the same time (diagonally) and touching the wall, character starts moving slower. (And start going Vertically or horizontally, but slower)
 

samspade

Member
Unless I'm missing something that code seems fine and is the standard and very well tested collision loop. This means the problem is likely elsewhere. Are all masks rectangles (e.g. both wall and moving objects) and have you checked for any other code which would move the player or change the player's movement? What does the player's movement code look like? For example if you are using 8 directional movement where you are limiting the speed on the diagonal so that all directions move at the same speed and you are doing this before collision, that would slow the character (and I think actually be the desired result).
 

Zabicka

Member
Unless I'm missing something that code seems fine and is the standard and very well tested collision loop. This means the problem is likely elsewhere. Are all masks rectangles (e.g. both wall and moving objects) and have you checked for any other code which would move the player or change the player's movement? What does the player's movement code look like? For example if you are using 8 directional movement where you are limiting the speed on the diagonal so that all directions move at the same speed and you are doing this before collision, that would slow the character (and I think actually be the desired result).
Every Collision mask is rectangle.
This is the movement code:
Code:
// Key input
var hinput = keyboard_check(ord("D")) - keyboard_check(ord("A"));
var vinput = keyboard_check(ord("S")) - keyboard_check(ord("W"));

// Movement
if (hinput != 0 || vinput != 0) {
    dir  = point_direction(0, 0, hinput, vinput);
    hspd = lengthdir_x(move_speed, dir);
    vspd = lengthdir_y(move_speed, dir);
   
    // Collision
    if (hspd != 0 || vspd != 0) {
        collision();
    }
}
And this is the collision script:
Code:
// Horizontal
if (place_meeting(x + hspd, y, obj_wall)) {
    while (!place_meeting(x + sign(hspd), y, obj_wall)) {
        x += sign(hspd);
    }
    hspd = 0;
}
x += hspd;

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

samspade

Member
So with that movement code the result your getting is expected as noted in my above post and probably desired. I'll try to explain.

Assume movement speed is 10. If h and v spd are set independently then moving horizontally will give you a speed of 10 and moving vertically will give you a speed of 10 but moving diagonally will give you a speed of just over 14. You probably already know this because you've used code to limit your diagonal movement speed to 10. But this means that if you are moving diagonally your h a v spd respectively are both just over 7. Since these values are set before collision checking when the collision checker reduces one of them to 0 the other one remains but at the lower speed necessary for correct diagonal movement.

You could test the above pretty easily by putting some show debug messages in to print out the hspd and vspd values. See Using show_debug_message if that doesn't make sense.

To fix the problem you'd have to either check for a wall collision before setting movement or add the spd back in after checking for a collision.

Code:
// Key input
var hinput = keyboard_check(ord("D")) - keyboard_check(ord("A"));
var vinput = keyboard_check(ord("S")) - keyboard_check(ord("W"));

// Movement
if (hinput != 0 || vinput != 0) {

    if (place_meeting(x, y + vinput, obj_wall)) vinput = 0;
    if (place_meeting(x + hinput, y, obj_wall)) hinput = 0;

   dir  = point_direction(0, 0, hinput, vinput);
   hspd = lengthdir_x(move_speed, dir);
   vspd = lengthdir_y(move_speed, dir);
 
   // Collision
   if (hspd != 0 || vspd != 0) {
       collision();
   }
}
I haven't tested that so it might take some tweaking but that would be the general idea. I would test both though as what the above code will mean is that if a player runs diagonally into a wall they will appear to speed up.

As a test, I tired it out in Children of Morta (a recent 2D top down game) and their movement also slows down when running diagonally against a wall.
 
Last edited:

Zabicka

Member
So with that movement code the result your getting is expected as noted in my above post and probably desired. I'll try to explain.

Assume movement speed is 10. If h and v spd are set independently then moving horizontally will give you a speed of 10 and moving vertically will give you a speed of 10 but moving diagonally will give you a speed of just over 14. You probably already know this because you've used code to limit your diagonal movement speed to 10. But this means that if you are moving diagonally your h a v spd respectively are both just over 7. Since these values are set before collision checking when the collision checker reduces one of them to 0 the other one remains but at the lower speed necessary for correct diagonal movement.

You could test the above pretty easily by putting some show debug messages in to print out the hspd and vspd values. See Using show_debug_message if that doesn't make sense.

To fix the problem you'd have to either check for a wall collision before setting movement or add the spd back in after checking for a collision.

Code:
// Key input
var hinput = keyboard_check(ord("D")) - keyboard_check(ord("A"));
var vinput = keyboard_check(ord("S")) - keyboard_check(ord("W"));

// Movement
if (hinput != 0 || vinput != 0) {

    if (place_meeting(x, y + vinput, obj_wall) vinput = 0;
    if (place_meeting(x + hinput , y, obj_wall) hinput = 0;

   dir  = point_direction(0, 0, hinput, vinput);
   hspd = lengthdir_x(move_speed, dir);
   vspd = lengthdir_y(move_speed, dir);
  
   // Collision
   if (hspd != 0 || vspd != 0) {
       collision();
   }
}
I haven't tested that so it might take some tweaking but that would be the general idea. I would test both though as what the above code will mean is that if a player runs diagonally into a wall they will appear to speed up.

As a test, I tired it out in Children of Morta (a recent 2D top down game) and their movement also slows down when running diagonally against a wall.
It doesn't work for some reason. I tried it and my character is now moving when colliding with a wall, but only when colliding with vertical wall, when colliding with left wall, it bounces around.
 

samspade

Member
It doesn't work for some reason. I tried it and my character is now moving when colliding with a wall, but only when colliding with vertical wall, when colliding with left wall, it bounces around.
Post your code and attempt to debug it yourself as well (rather than just saying it doesn't work). For this I would probably use some show debug messages to see what the various values are.
 

Zabicka

Member
Post your code and attempt to debug it yourself as well (rather than just saying it doesn't work). For this I would probably use some show debug messages to see what the various values are.
Sorry for no response, but I fixed it, after one day.
Here is the code:
Code:
// Movement
if (place_meeting(x + hinput, y, obj_wall)) { hinput = 0; }
if (place_meeting(x, y + vinput, obj_wall)) { vinput = 0; }

if (hinput != 0 || vinput != 0) {
    dir  = point_direction(0, 0, hinput, vinput);
    hspd = lengthdir_x(move_speed, dir);
    vspd = lengthdir_y(move_speed, dir);
   
    // Collision
    if (hspd != 0 || vspd != 0) {
        collision();
    }
}
Thank you!
 
Top