I made a little game with side-scrolling and a box (the player) jumping across the level. The simple physics are almost done, but I have two problem with the way things behave:

  • On landing, the box takes a little time to reach the floor
  • When the box hit a roof, there is always a little space between it and the object.

Here is my collision code (in the player's Step Event):

myGravity = 0.5;
if (vspeed > 10)  vspeed = 10;

speedAir = abs(vspeed+1);

//ON_FLOOR = !(place_free(x, y + speedAir));
ON_AIR = place_free(x, y + speedAir);

FREE_RIGHT = place_free(x + speedScreen, y); 
FREE_UP = place_free(x, y - speedAir);

KEY_UP = keyboard_check(vk_up);
KEY_LEFT = keyboard_check(vk_left);
KEY_RIGHT = keyboard_check(vk_right);
KEY_FIRE = keyboard_check(vk_space);

/* JUMP */
    gravity = myGravity;
    gravity_direction = 270;

    if !(FREE_UP)
        vspeed = 0;

else // if ON_FLOOR
    gravity = 0;
    gravity_direction = 270;
    vspeed = 0;

    // JUMP
    if KEY_UP & FREE_UP
        vspeed = -10;

    x += speedScreen; // screen side-scrolling

How can I do this correctly?


The problem

I think the main flaw is that you're checking if the object is in the air using the code place_free(x, y + speedAir). That's effectively like this:

two IN_AIR checks that say no, a third that says yes

Imagine your object is shaped like that blue J-tetromino and the ghost version of it represents its position + its speed; where it will be next frame. The yellow is a floor.

At the first two speeds, it's correctly determined as being in the air. In the third, the place_free check fails because the ghost intersects something, and so ON_AIR == false even though the object is nowhere near the ground!

The fix

It might be worth reading up on collision detection (Metanet's tutorial on separating axis theorem is pretty great), but here's one simple-ish method: To make sure the character stops exactly on the ground, you could first of all check only for place_free(x, y), and use the object's position relative to the ground object to calculate how much they intersect by. Then just move the object out by that amount.

simple collision response

  • 1
    \$\begingroup\$ Also, take care that objects cannot move through the floor entirely in a single frame. \$\endgroup\$ – Simon Richter Apr 20 '15 at 5:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.