Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

With regards to this question; how can I determine where the ball should bounce when it hits the bottom bar?

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.

Thanks a lot for the help.

share|improve this question
    
Write pong before breakout, you could then export the ball, wall and paddle classes and extend them such that they work with the different types of bricks and powerups. Plus, I would consider pong simpler than breakout. –  Incognito Oct 5 '10 at 19:53

7 Answers 7

up vote 16 down vote accepted

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.

share|improve this answer
    
That effect is what I'm going for; the faster speed as it hits the edges of the bar. Thanks a bunch for taking the time to write this out. I'm having some trouble understanding a few things though; for example, in the first snipper, what is 'intersectY'? Also, 'paddle1Y' is the height of the bar correct? –  Sergio Oct 2 '10 at 22:57
    
intersectY is the position of the ball where it intersects the paddle. I do an overcomplicated calculation which I honestly don't even understand right now, but essentially it is the Y value of the ball at the time it collides. paddle1Y is the Y value of the paddle, from the top of the screen; PADDLEHEIGHT is the height of the paddle ("bar"). –  Ricket Oct 2 '10 at 22:59
    
What would you have to add in order to allow "curve" balls? For example, when the ball is about to hit the paddle you move the paddle in order to make the ball curve. Something like this: en.wikipedia.org/wiki/Curve_ball –  Zolomon Oct 7 '10 at 17:59
    
See the edit, and let me know what you think (if you need more info about something, don't get something, etc.) –  Ricket Oct 7 '10 at 23:26
    
Thanks! Superb answer, I've always wondered how to do achieve that effect! –  Zolomon Oct 9 '10 at 7:31

It has been a while since I've done this, but I think I've got this right.

Given a perfect collision, the angle of reflection is equal to the angle of incidence.

You know the normal of your paddle (presuming a flat surface): N You know your original position of your ball (at the beginning of your timestep): P You know your new position of the ball (at the end of the timestep): P' You know your point of collision: C Assuming that you calculated that the segment P -> P' passes through your paddle, your new reflected postion (P'') would be:

P' + 2 * (N * (P' dot -N) )

The N * (P' dot -N) subexpression calculates the depth along the normal of collision the ball traveled. The minus sign is to correct for the fact we're checking for depth opposite the direction of the normal.

The P' + 2 * the part of the subexpression moves the ball back above the plane of collision by 2 times the depth of the collision.

If you want a less than perfect collision, change the factor 2 to be (1 + (1-k)) where k is your coefficient of friction. A perfect collision has a k value of 0, causing the reflection angle to be exactly that of the incoming angle. A k value of 1 causes a collision where the ball would stay on the surface of the plane of collision.

Your new velocity vector, V'', direction would be P'' - C. Normalize it and multiply by your incoming velocity and your resultant velocity magnitude would be the same, but in the new direction. You can monkey with that velocity by multiplying it by a coefficient, l, that would either increase (l > 1) or decrease (l < 1) the resulting velocity.

To summarize:

P'' = P' + (1-k) * (N*(P dot -N)) V'' = l * V * ((P'' - C) / |P''-C|)

Where k and l are coefficients of your choosing.

share|improve this answer

I'm making an arkanoid-ish game myself too and I think the solution on how the ball should behave when hitting the paddle is quite simpler and faster than getting into the sin/cos approach... it works fine for the purposes of a game like this. Here's what I do:

  • Of course, since the ball speed increases in time I interpolate the before/after x,y steps to keep accurate collision detection, looping through all "stepX" and "stepY" which are calculated dividing each speed component by the modulus of the vector formed by the current and future ball positions.

  • If a collision against the paddle occurs I divide the Y speed by 20. This "20" is the most convenient value I found to get my resulting maximum angle when the ball hits on the sides of the paddle, but you can change it to whatever your needs are, just play with some values and choose the better for you. By dividing, let's say a speed of 5, which is my initial game speed by this number (20), I get a "rebound factor" of 0.25. This calculation keeps my angles quite proportional when the speed increases in time up to my maximum speed value which, for example, could be 15 (in that case: 15/20 = 0.75). Considering that my paddle x, y coords are midhandled (x and y represent the center of the paddle), I then multiply this result by the difference between the ball position and the paddle position. The greater the difference, the greatear the resulting angle. Besides, using a midhandled padlle, you get the correct sign for the x increment depending on the side the ball hits without having to worry about calculating the center. In pseudo-code:

For n = 0 to modulus ...

if collision_detected then speedX = -(speedY / 20 ) * (paddleX - ballX); speedY = -speedY;
exit; end if

...

x = x + stepX; y = y + stepY;

end for

Remeber, always try to keep things SIMPLE. I hope it helps!

share|improve this answer

The paddle in Breakout, when it follows the style you're describing is usually modelled as a curved surface. The angle of incidence changes based on where on the paddle it hits. On the dead center the tangent line to the curve is absolutely horizontal, and the ball reflects as expected. As you move off the center, the tangent to the curve becomes increasingly angled, and the ball reflects differently as a result.

The key point is that the angle of reflection, not the ball speed, is what changes. The ball speed generally just increases slowly over time.

share|improve this answer
1  
You say as a curved surface and that sounds logical in my head but once I try to think of it in terms of code things get fuzzy fast. How could I even declare that in code as a variable or something. –  Sergio Oct 2 '10 at 22:46
    
Something like angle = 1 - 2 * (ball.x - paddle.left) / paddle.width will give you a number between 1 and -1; this (times some value tweaked for your game mechanics) is the slope of the tangent line at the point the ball collided. Reflect off that line rather than the strictly horizontal one. –  user744 Oct 2 '10 at 23:00

Nolan Bushnell gave a keynote at SIEGE this past weekend and talked about a similar issue with the original pong. You don't have to do alot of complicated calculations. If you hit on towards the left portion of hte panel, send the ball left. Do the same for the right side.

To start off with you can make the angle for the left and right sides 45 degrees. Once you finish the game you could if you want go back and make this more complicated but make this as simple as you can to begin with.

share|improve this answer
    
I saw that keynote too, his point was that this was a design decision not a math decision: "angle of incidence = angle of reflection" would be correct but make for weak gameplay. Additionally in the original Pong and Breakout, speed was a function of how many ball/paddle collisions there were (so it speeds up over time). They also reduced paddle size after a certain number of hits, too. I would avoid allowing the ball to go straight up though, then you could leave the paddle there indefinitely. –  Ian Schreiber Oct 5 '10 at 15:18

Breakout is a classic beginners work for starting to dive into the world of physics based game programming. Basically the ball has a bounce motion when it hits on the wall. As somebody above suggested the angle of incidence is equal to the angle of reflection. But when you consider the ball hitting the paddle. The logic is divided into 3 sections. 1.) The ball hitting the center portion of the paddle. 2.) The ball hitting the leftward portion of the paddle. 3.) The ball hitting the rightward position of the paddle.

When you consider the center portion: You need not differ the bounce effect of that which is applied when hitting the ball. The ball just gets deflected normally.But, when either direction is hit, the case is different.

When the ball is hit on the leftward side, ie consider the ball coming from the leftward side of the screen and you are coming with the paddle from the right side. Then when you hit the ball with the leftward portion, the ball should reflect to the direction it came from .ie.leftwards with the same angle it came from. Same is the case vice versa. In the rightward portion also the same thing applies.

This movement of the ball towards the leftward or rightward direction when it is being hit makes it more believable.

Hope you got the idea,at least logic wise.Thank you

share|improve this answer

The reflection can either be done "right" or done "easy."

The "right" way is to compute vectors perpendicular to the walls. In 2D that's pretty easy and you could probably just hard code them. Then, the reflection step essentially leaves the "parallel" component of the motion intact and reverses the "perpendicular" component. There's probably detailed information on the web for this, maybe at MathWorld even.

The "easy" way is to just negate the X or Y motion when you hit a wall. If you hit the side walls, you'd negate X. If you hit the top you negate Y. If you want to speed the ball up, just increase whatever you want; you can speed it up in its current direction by multiplying both the X and Y speeds or you can speed up only on one axis.

share|improve this answer
    
Aren't the "easy" way and the "right" way described above essentially the same?? –  Tom Jun 22 at 11:01
    
They are exactly the same if the walls are along the major axes. If the walls are not all along the X, Y, and Z axes then no, the two are completely different. –  dash-tom-bang Jun 23 at 17:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.