Thursday, February 9, 2017

xna - In Pong, how do you calculate the ball's direction when it bounces off the paddle?


I'm trying to wrap my head around this very Hello World-y problem in game development. I've created a TicTacToe game in XNA so I guess the next step would be a Breakout clone.


Keep in mind that I have no knowledge on game programming or even what maths I should apply to where. That's why I'm asking this question.




To the question: How can I determine where the ball should bounce when it hits the paddle at the bottom of the screen?


I'd imagine it would be something like:




  1. Capture speed and angle from incoming ball.

  2. Detect where it touched the bar (far left, far right, center) and according to that give it a higher speed if it touched the outer areas.

  3. This is where I'm stuck. Hehe.


Any insights? I realize this is not a straightforward answer type question, but I'm sure it's one everyone faces at some point.


I'm reading the book Linear Algebra that was recommended on this website, but I still have no idea if I should apply it here.



Answer



Here's the relevant logic I used on the pong on my homepage: (please go play it before reading, so that you know the effect I'm achieving with the following code)


Essentially, when the ball collides with the paddle, its direction is completely disregarded; it is given a new direction according to how far from the center of the paddle it collided. If the ball hits the paddle right in the center, it is sent away exactly horizontal; if it hits right on the edge, it flies off at an extreme angle (75 degrees). And it always travels at a constant speed.



var relativeIntersectY = (paddle1Y+(PADDLEHEIGHT/2)) - intersectY;

Take the middle Y value of the paddle, and subtract the Y intersection of the ball. If the paddle is 10 pixels high, this number will be between -5 and 5. I call this the "relative intersect" because it is in "paddle space" now, the ball's intersection relative to the middle of the paddle.


var normalizedRelativeIntersectionY = (relativeIntersectY/(PADDLEHEIGHT/2));
var bounceAngle = normalizedRelativeIntersectionY * MAXBOUNCEANGLE;

Take the relative intersection and divide it by half the paddle height. Now our -5 to 5 number is a decimal from -1 to 1; it's normalized. Then multiply it by the maximum angle by which you want the ball to bounce. I set it to 5*Pi/12 radians (75 degrees).


ballVx = BALLSPEED*Math.cos(bounceAngle);
ballVy = BALLSPEED*-Math.sin(bounceAngle);


Finally, calculate new ball velocities, using simple trigonometry.


This might not quite be the effect you're going for, or you might want to also determine a speed by multiplying the normalized relative intersection by a max speed; this would make the ball go faster if it hits near the edge of a paddle, or slower if it hits near the center.





I'd possibly like some code on what a vector would look like or how I could save the variable of the vector the balls has (speed and direction).



A vector contains both speed and direction, implicitly. I store my vector as a "vx" and "vy"; that is, the speed in the x direction and the speed in the y direction. If you haven't taken an introductory course in physics this might seem somewhat foreign to you.


The reason I do this is because it reduces the per-frame calculations necessary; every frame, you just do x += vx * time; and y += vy * time; where time is the time since last frame, in milliseconds (therefore the velocities are in pixels per millisecond).




Regarding implementing the ability to curve the ball:



First of all, you'd need to know the paddle's velocity at the time the ball hits; which means you'd need to keep track of the paddle's history, so that you can know one or more of the paddle's past positions so that you can compare them to its current position to see if it moved. (change in position / change in time = velocity; so you need 2 or more positions, and the times of those positions)


You now also need to track an angular velocity of the ball, which practically represents the curve along which it is traveling, but is equivalent to the real-world spin of the ball. Similar to how you would interpolate the bounce angle from the relative position of the ball on collision with the paddle, you would also need to interpolate this angular velocity (or spin) from the velocity of the paddle on collision. Rather than simply setting the spin like you do with the bounce angle, you might want to add or subtract to the ball's existing spin, because that tends to work well in games (the player can notice the ball is spinning, and cause it to spin even more wildly, or counter the spin in an attempt to make it travel straight).


Note, however, that while this is the most common sense and probably easiest way to implement it, the actual physics of a bounce doesn't rely solely on the velocity of the object it hits; an object with no angular velocity (no spin) which hits a surface at an angle, will have a spin imparted upon it. This might lead to a better game mechanic, so you may want to look into this, but I'm not certain of the physics behind it so I'm not going to try to explain it.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...