Jump to content
  • Advertisement
Sign in to follow this  
null;

SFML Odd Collision

This topic is 571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Edited by Debz

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.

Edited by Debz

Share this post


Link to post
Share on other sites

The logic is as simple as the pseudocode demonstrates.

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Edited by felipefsdev

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!