- Home /
Creation of an algorithm that deflects the ball correctly at all possible paddle angles in a Breakout style game
Hi, my name is Maikel and I have been using Unity for a bit now. Mostly learning purposes and small projects. My latest project is a Breakout styled game. I have ran into a problem with the design of the paddle-ball collision system and I just can't figure it out, hence my ask for your help.
The unique selling point/ feature of the game is that it has circular movement. The player can move around a circle and has to defend an inner circle. This makes it that all systems: movement and such are a little more complex.
So far I have been able to handle it but I can't seem to make the ball-paddle collision work properly. The design I'm hoping to implement correctly is that when the ball hits the right side it is deflected to the right and when its hits the left side it is deflected to the left.
I have implemented a function that uses the position of the collision to determine how to deflect the ball. I have read much about the use of this system and it works quite well but I can't figure out to alter it to my needs. The function reflects the incoming velocity vector of the ball with the collision contact normal of the paddle.
It negates or does not negate the y value of the velocity based on the position of the ball.
private void DirectionalMovement(Vector2 ballPos,Collision2D collider)
{
Vector2 racketPos = collider.transform.position;
float racketWidth = collider.collider.bounds.size.x;
float x = (ballPos.x - racketPos.x) / racketWidth;
Vector2 dir = new Vector2(x, 1).normalized;
if (this.transform.position.y <= 0)
{
dir = new Vector2(x, -1).normalized;
}
ballRigidbody.velocity = dir * speed;
}
This works, but not good enough. The main problem with this approach is that it leaves, what I call, "dead-zones", some areas that the ball can't reach when bouncing of the paddel. I have illustrated them in the picture below, along with some extra information.
I have been thinking about the problem a lot and can't seem to come up with a solution to the problem or a system that would work. I'm not a pro when it comes to geometry and vectors, though I can understand them I haven't been able to use them to solve this problem.
Can someone guide me to the right direction for solving this specific problem. I am not asking for a clear-cut answer or algorithm. Just a general direction for me to look , because I seem to be lost. Thanks in advance! (Pardon my grammar if it is incorrect in some places, English is not my native language)
Answer by Bunny83 · Mar 11, 2017 at 11:39 AM
Well, your problem is that you use an "absolute reflection angle". In games where the paddle is always oriented horizontally that's not a big deal. However when you rotate your paddle it makes not much sense.
You may want to calculate everything in local space of the paddle:
Vector2 ballLocalPos = collider.transform.InverseTransformPoint(ballPos);
float x = (ballLocalPos.x) / racketWidth;
Vector2 dir = new Vector2(x, 1);
if (ballLocalPos .y <= 0)
dir.y = -dir.y;
dir = collider.transform.TransformDirection(dir).normalized;
ballRigidbody.velocity = dir * speed;
It should be obvious that this approach in general doesn't result in a realistic reflection (ignoring the fact that a straight paddle is handled like a curved paddle). Since you calculate a fix direction in which the ball will bounce off, it doesn't matter at which angle it arrives.
From your drawing it looks a bit like Shield Defence ^^. Though that game uses the correct angle of reflection.
Was going to answer similarly, I had started drawing up an image in case it is helpful, the important part to note is; based on your desired 'inco$$anonymous$$g' and 'outgoing' vectors, the important vector to extract is the one that is in the middle of them both as this acts as the reflection normal as shown by the grey line in the first image! +1 for both of ya,good job added some images to the question @$$anonymous$$asterTakeshi
I hadn't thought about the local and global concept because I hand't used it in such way before. This solution works very well for my use case. Thank you kindly for this valuable insight!