简体   繁体   中英

Pong Paddle collision velocity and rebound angle

Well I've searched a lot for this but all I can find is people saying like do pi * direction, direction being the angle that the ball is coming in at I assume. But my problem is, I have no idea how I get the angle the ball is coming in at in the first place so I can't do these. If anyone could explain how I would calculate the angle that the ball has hit the paddle hat, the amount of velocity that the ball should be given after rebound and the angle it should be incremented by then that would be awesome.

Thankyou for any and all responses!

My code works as follows (So you can get an idea of how I'd like to do it):

/* General Paddle Properties */
double PaddleLength = 80;  //Down-wards length of the paddle
double PaddleWidth = 8;  //How thick the paddle is

/* Positioning of user control paddle */
double UserPaddleTop = 0;  //How far away from the top of the screen the paddle is
double UserPaddleLeft = 10;  //How far left from the side of the client rectangle it is

/* Positioning of ai controled paddle */
double AIPaddleTop = 0;
double AIPaddleLeft = 10;

/* Ball properties and position */
double BallSize = 5;
double BallTop = 0; 
double BallLeft = 0;
double BallSpeedY = -0.01, BallSpeedX = -0.03;

Methods:

private void UpdateBall()
        {
            if (((int)(UserPaddleLeft + PaddleWidth) == (int)BallLeft) && !((int)UserPaddleTop > (int)BallTop) && !((int)(UserPaddleTop + PaddleLength) < BallTop) 
                || ((int)(AIPaddleLeft - PaddleWidth) == (int)BallLeft) && !((int)AIPaddleTop > (int)BallTop) && !((int)(AIPaddleTop + PaddleLength) < BallTop)) //Collided
            {
                BallSpeedX = -BallSpeedX; //The height is 800 the balltop is 300
                BallSpeedY = Math.Cos(BallSpeedX
            }

            if ((int)BallTop == 0 || (int)BallTop == ClientRectangle.Height) //Hit the top 
            {
                BallSpeedY = -BallSpeedY;
            }

            if ((int)BallLeft == 0)
            {
                System.Diagnostics.Debug.WriteLine("AI gets one point!");
                BallSpeedX = -0.03; //Goes towards the user AI has scored
                Scores[0]++;
                this.Title = "Pong Testing - Scores: " + Scores[0] + "|" + Scores[1];
                ResetAll();
            }
            else if ((int)BallLeft == ClientRectangle.Width)
            {
                System.Diagnostics.Debug.WriteLine("User gets one point!");
                BallSpeedX = 0.03; //Goes towards the AI user has scored
                Scores[1]++;
                this.Title = "Pong Testing - Scores: " + Scores[0] + "|" + Scores[1];
                ResetAll();
            }

            BallLeft = (BallLeft + BallSpeedX);
            BallTop = (BallTop + BallSpeedY);
        }

        private void UpdateAI()
        {
            if(!((int)(BallTop + PaddleLength) == 0) && !( (int)(BallTop + PaddleLength) >= ClientRectangle.Height ) ) //Make sure updating it pos won't make it go out of bounds
                AIPaddleTop = BallTop; //Change to real ai by using offset
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            if ( (int)UserPaddleTop != 0 && Keyboard[Key.Up])
            {
                UserPaddleTop = UserPaddleTop - MoveSpeed;
            }
            else if (Keyboard[Key.Down] && (int)(UserPaddleTop + PaddleLength) != ClientRectangle.Height)
            {
                UserPaddleTop = UserPaddleTop + MoveSpeed;
            }
        }

UPDATE 1:

Thanks to the help of everyone I have been able to come up with some basic code for it but now this code just sends the ball flying so fast that it's impossible to get it. Could anyone help please?

Code:

        double AngleNormal = Math.Atan2(BallSpeedX,BallSpeedY);
        double AngleBallMovement = Math.Sqrt((BallSpeedX * BallSpeedX) + (BallSpeedY * BallSpeedY));
        double ReflectionAngle = AngleNormal - (AngleBallMovement - AngleNormal);
        BallSpeedY = Math.Sin(ReflectionAngle);
        BallSpeedX = Math.Cos(ReflectionAngle);

In the simplest sense (ignoring ball spin, friction, paddle movement, etc.) is to work out the angle of incidence relative to the surface normal and invert it. In the context of simple physics collisions, angle of incidence is the angle of movement of the ball relative to the normal of the surface of the paddle at the point of collision. In an arbitrary coordinate space the calculation is something like:

angleReflect = angleNormal - (angleBallMovement - angleNormal)

For a very simple case of a true rectangular paddle the normal is going to be perpendicular to the paddle's axis of motion. This gives you very little control over the ball, since the reflection angle is always going to be purely a function of the direction the ball is moving.

You can simulate a curved paddle surface by varying the normal vector of the paddle's surface based on the distance from the center of the paddle that the ball impacts. This allows the player to change the ball's movement angle by intercepting the ball off center on the paddle to get a steeper or shallower reflection angle.

The real fun is when you start adding friction, spin and paddle motion calculations to the mix. Gets a bit much for most players to keep track of, but allows for some interesting trick shots :)

--

As for how to calculate the angles, the trig function Math.atan2(x, y) will give you an angle (in radians) for a given [x,y] velocity vector, and Math.sqrt(x*x + y*y) gives you the length of the movement vector. This gives you a line that you can intersect with the surface of the paddle (factoring in the radius of the ball, if you're into accuracy) to get the point of impact. The remaining portion of the movement 'line' is reflected using the angle of incidence and whatever other calculations you add, giving a final position of the ball and new velocity vector.

A laser pointer and a mirror are good visualization tools for this :)

In order to calculate an angle, you have to know what direction the ball is moving in. You have that information in your BallSpeedX and BallSpeedY values. Say your original position is (0, 0), BallSpeedX is 2, and BallSpeedY is 3. So you have a right triangle with one side being 2 and the other being 3, and you can use simple trigonometry to figure out the angle.

Now, the paddle is probably parallel with the X axis, so you have to compute the angle relative to that axis. But that shouldn't be too tough.

Once you know the angle that the ball hits the paddle, you just subtract that value from 180 degrees (or pi radians), and that's new angle. So if the ball hits the paddle at 60 degrees, it's going to bounce off at 120 degrees. That's assuming no spin, perfect elasticity, no paddle movement, etc.

The ball's speed when it comes off the paddle is up to you. You can assume no energy loss and give the ball the same speed coming off the paddle as going on. Or you can say that a bounce absorbs 10% of the ball's energy, in which case you'd want to reduce the ball's velocity by 10% (but don't just subtract 10% from the X and Y speed values, or you'll change the angle).

Clear as mud now?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM