Bouncing Projectile passing through wall of blocks

I am firing a ball at a wall that is built of bricks, if it is close enough to the seam the ball will start zigzagging and eventually pass through the wall…

image

This is how I calculate the reflection. It works well when it collides around the middle of the Block.

    public static Vector2 FromToTOVelocity(Vector2 from, Vector2 to)
    {
        float angle = (float)Math.Atan2(to.Y - from.Y, to.X - from.X);
        return new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
    }

    private Vector2 ReflectFromRect(Rectangle projectile_rect, Rectangle wall_rect, Vector2 proj_vel){
        Rectangle intersects = Rectangle.Intersect(projectile_rect, wall_rect);
        Vector2 intersectsNorm = FromToTOVelocity(projectile_rect.Center.ToVector2(), intersects.Center.ToVector2());
        return Vector2.Reflect(proj_vel, intersectsNorm);
    }

Any idea how I can fix this?
I have been thinking I should try to detect the side it is closest to and then enlarge the rectangle it is using to calculate the reflection. But I am not quite sure how to achieve that.
Any ideas?

@Lajbert has an article on this subject that may help:

2 Fast 2 Curious: collision detection with fast moving objects

1 Like

@Lajbert Thank you for the response, I will read the article, but I won’t have time today. So, I will be in touch. :slight_smile:

1 Like

Thank you for the article, it was very informative and has helped improve the quality for my bounce a great deal.
There are still some bugs . But when I manage to hit the seam dead on. Then this happens.

ezgif.com-gif-maker (1)

This my code ‘ReflectFromRect’ method is the same as in my original post.


    private void UpdateReflectors(){
        if(reflect == true){

            Vector2 new_vel_ctrl = new Vector2( vel_ctrl.X,  vel_ctrl.Y);
            Vector2 new_pos = new Vector2(position.X, position.Y);
            Vector2 previous_pos = PreviousPos();
            Vector2 next_pos = NextPos();


            float lerpIndex = 0.05f;


            while(lerpIndex < 1.1f){
                Vector2 lerp_pos = Vector2.Lerp(previous_pos, next_pos, lerpIndex);

                var current_rect = RectFromPos(lerp_pos);
                if(current_rect.Intersects(reflect_colliding_0) ){

                    new_pos = lerp_pos;
                    new_vel_ctrl = ReflectFromRect(current_rect, reflect_colliding_0, vel_ctrl);
                    break;
                }
                else if( reflect_colliding_0 != reflect_colliding_1 && current_rect.Intersects(reflect_colliding_1) ){
                    new_pos = lerp_pos;
                    new_vel_ctrl = ReflectFromRect(current_rect, reflect_colliding_1, vel_ctrl);
                    break;
                }
                lerpIndex += 0.05f;
                
            }

            position = new_pos;
            vel_ctrl = new_vel_ctrl;
            reflect = false;
        }
    }

I am logging a second reflect_colliding_1 in case there would be a second one in the same loop, but this never seems to happen.

At higher speed it works better though, So I might just leave it as is for now.

ezgif.com-gif-maker (2)

I would incooperate some break point which interrupts when the tunneling happens to find the exact reason for why it happens - like break, when the bullets new position would end up inside a blocked tile. Could be as easy as clamping the position to some fixed floating precision. Lots of guessing here otherwise :slight_smile:

1 Like

I remember I had similar issue in one of my games like you. So my solution was to consolidate all the blockers into one big block so that will never happen.
For example: if you have :
x x x
where each x is a block
i changed all of them into one big block as a rectangle
so I had a pre-process of the scene which will consolidate all blocks as much as possible.

2 Likes

Thanks ,will try , but I’ll need to wait till the I get some time off.

Thanks for the suggestion, I had done this previously as well. But then I was planning to make them breakable at times, and I wanted to make it easier to interact with them separately later on. I will give it a go when I find some time. :slight_smile:

Just wanted to update, I am currently rewriting my spatial grid that runs the collision detection.
I never took into account collisions that might get skipped by higher speeds.
So I will fix that first then get back to you, Hopefully I can get something running by tomorrow.
Before it was strictly 1 rectangle per entity.
I will try to make a system where each Entity with velocity ends up being checked on multiple rectangles that might have happened in between. Will update later. Have a nice weekend :slight_smile:

You want to calculate the time of impact (a value between 0 and 1) where 1 is the full length of that frames movement and 0 is no movement. If your ball impacts 0.25% of the movement of that frame, then you can multiply your veloctiy by 0.25, move, bounce, then move your ball the rest of the 0.75 movement (and check for collision.

Also, if your ball is going to be super fast, then calculate the amount of units your expecting it to move. If its more than a certain amount, you can do the collision checking at various points (eg for every 5 units do a collision check until you hit something) but you should also do a broad phase check too, only check against objects close by

Robust collision detection is difficult to get right

1 Like

@boot thank you for your suggestions.

I am still rebuilding my spatial grid to accommodate high travel distance per frame.
Your second paragraph is more or less what I am working on at the moment. But it’s mostly outside of workdays. So it takes me a little more time.

Robust collision detection is difficult to get right

I can definitely relate to this: at no point during my childhood fantasies of building computer games; was I spending the better part of a season learning about the intricacies of collision detection. :sweat_smile:

I know, ive spent way to much time on it too. I managed to get circle to rectangle and rectangle reasonably good.

Rotated rectangles are the hardest. I could never quite Seperating Axis Thereom working correctly. It worked - however there was always a couple edge cases it went strange on.

I recommend watching some of the Coding Trains videos on youtube (highly recommended - such a good teacher) He generally codes in P5, but the concepts are the same. He has some good videos on quad trees, collision detection etc.

You can detect collisions with rectangles like this but you cannot SOLVE collision, ie react to them, if you just check for overlap. You need things like direction, and point of impact…

The point on the balls circumference, where it hits a surface or corner, THAT is what matters, NOT where on the brick it hits… Every point on every brick does the same thing… But the point on the ball will determine new dir / reflection of ball based on current dir vs impact point…
it doesn’t matter WHAT the ball hits. A corner or a surface, its ALL just a single point to the ball.

Once you know where on the ball the collision happens, you can get the direction to that point from the CENTER of the ball, and from THAT direction - and the direction of the ball, you get new direction.

1 Like