SFML Odd Collision

Started by
4 comments, last by penguinbyebye 6 years, 11 months ago

I have 4 rectangles attached to my player for collision detection. When the player collides with anything, it's moved back the opposite direction.

Here's some pseudo code to demonstrate how it works.


if(leftCollisionRectangle.intersects(otherRect)) {
player.move(1, 0); //player's position is set to its x, plus one 1, and the y isn't affected as it isn't checking for top or bottom collision in this example
}

So I'm moving the player in the opposite direction at its speed when it intersects with another rectangle.

This is the result:

(I'm drawing the player's collision rectangles to demonstrate the intersection)

https://gyazo.com/33b257b8ec5063b021a927d844a655ec

It works, but it's buggy. The player is getting pushed back more once the key is released. Is there anything wrong with the logic I'm using to keep the player from being able to move through the rectangle, or could it be some kind of other issue?

Advertisement

I think you're going to have to show more of your logic,and your actual code, for that to be answerable. We don't know when the above code gets called, and we don't know whether leftCollisionRectangle.intersects(otherRect) ceases to be true after the move operation.

I think you're going to have to show more of your logic,and your actual code, for that to be answerable. We don't know when the above code gets called, and we don't know whether leftCollisionRectangle.intersects(otherRect) ceases to be true after the move operation.

It gets called before the keyboard logic function is called, in the main class. leftCollisionRectangle.intersects(otherRect) is false after the keyboard is released and the odd player movement occurs, but it's true while the player is actively moving into the rectangle.

The logic is as simple as the pseudocode demonstrates.

The logic is as simple as the pseudocode demonstrates.

You're going to end up nowhere fast with that attitude.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

You're going to need to show some actual code, and explain exactly what the problem is (as that video isn't exactly enlightening).

You need to show more code, but I will say what I think it's happening.

If this is your collision resolution code, then it's a naive approach:


if(leftCollisionRectangle.intersects(otherRect)) {
player.move(1, 0); //player's position is set to its x, plus one 1, and the y isn't affected as it isn't checking for top or bottom collision in this example
}

In some cases, solving the collosion after it happens is the desireable approach, like in 3D games with realistic physics, but for simple 2D games, with non realistic physics, it's better to predict the collision and then move to the correct position (or not move at all). In your case (from the pseudo code you show), you are solving collision after it happens.

Here is what you want:

Gather the input:


double velocity_x = 0.0;
double velocity_y = 0.0;
int32_t move_x = 0;
int32_t move_y = 0;
if (get_input("up")) {
    move_y = move_y - 1;
}
if (get_input("down")) {
    move_y = move_y + 1;
}
if (get_input("left")) {
    move_x = move_x - 1;
}
if (get_input("right")) {
    move_x = move_x + 1;
}
velocity_x = move_x * speed;
velocity_y = move_y * speed;

Now, we will predict the collision in the X axis:


if (overlap_at(this.shape, this.pos.x + velocity_x, this.pos.y, other_shapes_list)) {
    while (!overlap_at(this.shape, this.pos.x + sign(velocity_x), this.pos.y, other_shapes_list)) {
        /* Move the object 1 by 1 in the X axis while no collision happen */
        this.pos.x = this.pos.x + sign(velocity_x);
    }
    /* We solved a collision that would happen by setting the position of the object, now we 0 the velocity in the X axis */
    velocity_x = 0.0;
}
this.pos.x = this.pos.x + velocity_x;

After predicting and solving the X axis, we can predict and solve the Y axis:


if (overlap_at(this.shape, this.pos.y, this.pos.y + velocity_y, other_shapes_list)) {
    while (!overlap_at(this.shape, this.pos.y, this.pos.y + sign(velocity_y), other_shapes_list)) {
        /* Move the object 1 by 1 in the Y axis while no collision happen */
        this.pos.y = this.pos.y + sign(velocity_y);
    }
    /* We solved a collision that would happen by setting the position of the object, now we 0 the velocity in the Y axis */
    velocity_y = 0.0;
}
this.pos.y = this.pos.y + velocity_y;

The sign() function is just a function that convert the velocity value to 1, 0 or -1:


double sign(double d)
{
    double v = 0.0;
    if (d < 0.0) {
        v = d / -d;
    } else if (d > 0.0){
        v = d / d;
    }
    return v;
}

The way you are doing is pretty much how it would be done with Chipmunk2D or Box2D, but they are more for realistic physics than "classic"/"pixel-perfect-like" physics.

Also, since I don't know how you store the objects/shapes, I just referred to them as `other_shapes_list`. Note that you need to make a function like `overlap_at`, that will test if this shape is overlapping with any of the other shapes.

This topic is closed to new replies.

Advertisement