Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Find angle for pong game

This thread is locked; no one can reply to it. rss feed Print
Find angle for pong game
IroNuckles
Member #1,988
March 2002
avatar

Okay, I'm trying to modify my simple pong game to have realistic ball-bouncing action. How would I find the angle that the ball is making with the wall or paddle? Right now I'm just reversing the direction when a collision is detected.

DanTheKat
Member #1,990
March 2002
avatar

Actually i've been trying to find this out for ages.

---
"Even the best spellcaster can't transmute bread into bread." - spellcaster

gnudutch
Member #951
February 2001
avatar

IroNuckles, did it hurt when you got your neck pierced? ;)

Simple solution:

At collision, determine whether you hit a vertical wall (left and right side of playfield) or a horizontal wall (ceiling or your paddle). Then:

if (hit_vert_wall) x_speed = -x_speed;
if (hit_horiz_wall) y_speed = -y_speed;

Basically just invert one axis only and it will give you a perfect reflection.

Next thing I would add is variable angles provided by the paddle.

Derezo
Member #1,666
April 2001
avatar

Quote:

IroNuckles, did it hurt when you got your neck pierced? ;)

heh, I was wondering what you were refering to for a moment ;D

Well, in pong.. the ball really only goes 4 directions, right?
Either upleft, upright, downleft, or downright (45, 135, 225 or 315 degrees)..

In a very simple, and boring, pong game that I made quite some time ago I didn't use angles at all. I used 2 variables - horizontal direction, vertical direction..

updating post after rereading the original

If you want to use angles, I think you could add or subtract 90 (or 65 in allegdegress) to the angle whenever it hits the paddles or the borders...

"He who controls the stuffing controls the Universe"

IroNuckles
Member #1,988
March 2002
avatar

If you're referring to my mug shot, that's actually a ceiling fan in the background. :) I'm too lazy to edit the photo. ;)
Yeah, that's basicly what I have now, boring, terribly predictable bouncing ball. My question is, does allegro have sin and inverse sin functions or a vector class or something to calculate and change the angle with?

Derezo
Member #1,666
April 2001
avatar

Giving the ball a velocity which affects the direction it bounces in would give a bit more unpredictability, but... uhh.. I dunno how you could add an increasing/decreasing velocity in a game of pong..

"He who controls the stuffing controls the Universe"

superstar4410
Member #926
January 2001
avatar

heres something that does work

I made a pong game earler back in my days of early programming.

for the angle problem, I didn't use advance math

the ball had to varaibles
ball_x and ball_y

Ball_x = the x value the ball gets incremented

Ball_y = the y value the ball gets incremented

so if you like have a way that you like can hit like turbo hit, basically depending

on what angle the ball is coming from, increment
on of the other variables and the angle affect will be meet

like for sharp angles you will have
the ball moving with at a low Ball_x and an High Ball_y

so it would travel like

:o
/ /

/
/
/
/
/
/

/

/
/

/:)

And for lesser angles you would have the Ball_x incremented value high and the Ball_y value low

:)
/ >>>>> />>>>>>>>>. >>>:)

Don't take yourself too seriously, but do take your responsibilities very seriously.

Derezo
Member #1,666
April 2001
avatar

Sorta combines the velocity with the 'angle', nice :)

The only problem is, in a 'simple' game of pong, it's hard to make the ball "boost" forward without adding some sort of creative feature.. and who wants to do THAT? ::)

;)

"He who controls the stuffing controls the Universe"

Johan Halmén
Member #1,550
September 2001

Use variables d for direction, v for velocity.
vx = v * cos d
vy = v * sin d

When the ball gets its direction and velocity (depending on how it hits the pad) you use the sin and cos only once, to compute vx and vy. Then when the ball hits the walls, do vx = -vx or vy = -vy.

If the velocity changes, say if a turbo boost ends, just do vx = k * vx and vy = k * vy. k > 1 speeds up while k < 1 slows down.

If your new direction depends on the old direction when you hit the pad (or other objects) you may have to recompute the direction out of vx and vy. But actually, after any number of hits, your direction will be any of four possible directions. So when you determine vx and vy, determine also all 4 possible values for d.
Just keep track which direction is active.

Johan Halmén

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Mariusz
Member #1,634
November 2001

What I do is calculate where ball hits the pad
lets say that pad is 48 pixels wide so I get ball position and subtruct from pad position then devide by pads lenght and I get lets say 1/4 of pad which means it is left side of pad, same goes for the rest.
You also could devide your pad into more pieces like 8/8 where it will geive you more angles to use for ball.

Thomas Harte
Member #33
April 2000
avatar

If you mean you want angled walls, i.e. the simple 'reflecting just x or just y' approach that about 16,000 people have already explained on this thread isn't good enough, then as you speculate, you need to do a little vector maths. And Allegro won't help. But I will!

If the ball has velocity (vx, vy) and hits a wall which has the vector (wx, wy) - e.g. you draw the wall with line(bmp, x, y, x+wx, y+wy, col), then you can do this :

float r, l;
l = wx*wx + wy*wy;
r = (-wy*vx + wx*vy) / l;
vx += r*wy;
vy -= r*wx;

And if you're smart, you could observe that this is the same thing :

float r, l;
l = sqrt(wx*wx + wy*wy);
wx /= l;
wy /= l;

r = -wy*vx + wx*vy;
vx += r*wy;
vy -= r*wx;

And do the divides by l in your startup section rather than at every collision, saving a few calculations.

sicgamemaker
Member #1,365
June 2001
avatar

heres my shot at it... this is a entire article i got from some website (a long time ago, i forgot where) but here it is...its got good math for fast detection of collision, angled bounces, and mass/momentum transfer

#SelectExpand
1[CODE] 2Calculating a ricochet turns out to be a lot trickier problem than it 3first appears. For those of us who are a decade or more away from our 4last practice with algebra and trigonometry it requires some patience 5and perseverance. 6 7First we're going to concentrate on the collision of two balls. Later 8we'll expand that to the collision of a ball against a wall. Our 9discussion will include mass and elasticity. At the end we'll discuss 10some of our ideas on how we might handle simultaneous collisions 11between multiple objects. 12 13First, two balls. 14 15There are six parts to the calculation, with a couple of subparts. 16 17 1) Gross collision detection 18 2) Calculate accurate positions at time of collision 19 3) Calculate the angle of collision vs the velocity vector 20 4) Calculate portion of velocity vector that applies to collision 21 5) Calculate final velocities along collision vector 22 6) Apply final velocities back to the object 23 24--------------------------------------------------------------------- 25 1) Gross collision detection. 26 27The purpose of this step is to determine in as few instructions as 28possible whether the objects are close enough together to warrant more 29expensive calculations. There are many ways to accomplish this. The 30one we chose was the simple bounding box (See figures 1a through 1c). 31 32The quickest way to find out if two bounding boxes overlap is to test 33to see if the bounding boxes DON'T overlap. It only takes four tests 34to show that box A is to the right of, left of, above, or below box B. 35 36// Use this macro in an if statement. Ex. 37// if (bounding_box_test(ibx, ibx1, iby, iby1, jbx, jbx1, jby, jby1)) 38// DoSomething(); 39// else 40// DoSomethingElse(); 41#define bounding_box_test(ibx, ibx1, iby, iby1, jbx, jbx1, jby, jby1) \ 42 (!((ibx > jbx1) || (ibx1 < jbx) || (iby > jby1) || (iby1 < jby))) 43 44You'll need to extend the bounding boxes to include both the beginning 45and ending positions of each object. Otherwise, the objects could 46become overlapped before you detect a collision. 47 48--------------------------------------------------------------------- 49 2) Calculate accurate positions at time of collision. 50 51The central trick for this step is the Quadratic equation. 52 53Let's take a moment to define our terms. (See figure 2a) 54 55 Stuff we know: 56 x1,y1 and x2,y2 - The initial positions of the centers of the two objects 57 dx1,dy1 and dx2,dy2 - The distances the objects moved this frame 58 r1, r2 - radii of the two objects 59 60 Stuff we calculate: 61 t - Time of collision 62 cx1,cy1 and cx2,cy2 - The centers at time of impact 63 64What we're trying to find is when the centers of the two objects are 65the same distance apart as the sum of their radii. The distance 66formula is sqrt([cx1-cx2]^2 + [cy1-cy2]^2). Therefore, we're looking 67for the time (t) when 68 (r1+r2)=sqrt([cx1-cx2]^2 + [cy1-cy2]^2). 69 70How do we know where will a ball be at any given time (t)? Here are 71functions which describe the paths of the centers of the balls over 72time: 73 74 cx1 = x1 + tdx1 cx2 = x2 + tdx2 75 cy1 = y1 + tdy1 cy2 = y2 + tdy2 76 77The t's relate all the forumlas to each other. Replacing the cx's and 78cy's in the distance forumla with these equations and we end up with: 79 80 r1+r2 = sqrt(((x2 + tdx2)-(x1 + tdx1))^2 + ((y2 + tdy2)-(y1 + tdy1))^2) 81 82Multiply everything out then rearrange and simplify and you end up 83with: 84 85 0 = [(dx2-dx1)^2 + (dy2-dy1)^2] t^2 86 + [2(x2-x1)(dx2-dx1) + 2(y2-y1)(dy2-dy1)] t 87 + [(x2-x1)^2 + (y2-y1)^2 - (r1+r2)^2] 88 89This is a polynomial in the form 0=ax^2+bx+c. We can use the Quadratic 90equation (-b(+|-)sqrt(b^2-4ac))/2a to solve for the variable. The a, b 91and c are all spelled out above. You could plug a, b and c into that 92monster equation, but it turns out you want to calculate it in pieces. 93 94The Quadratic equation will give two answers, call them t1 and t2. One 95for each the plus and minus of the square root portion. There are some 96special cases to check before solving the equation, and some special 97cases that result from the equation. (See figure 2, cases 1-6) 98 99 1) If a=0 the equation goes infinite. Notice that "a" consists of the 100 square of the difference between the direction vectors. 101 Therefore, a=0 if and only if the balls are moving the same 102 direction and the same speed. 103 104 2) If 4ac > b^2 then you end up trying to take the square root of a 105 negative number. In other words, there's no solution. It turns 106 out that this happens if and only if the balls never pass within 107 r1+r2 of each other. Even though the paths may cross, the balls 108 are far enough apart in time that they don't approach close 109 enough to each other to ever actually touch. 110 111 3) If both t's are negative then the balls are receding from each 112 other. 113 114 4) If one t is negative and the other t is positive then the balls 115 began the frame already overlapped. 116 117 5) If both t's are positive then the smaller of the two is when they 118 first reach r1+r2 from each other. 119 120 6) If both t's are greater than 1.0 then the balls do not collide 121 this frame. 122 123Condition 5 is the only valid collision and you continue with the rest 124of the calculations. 125 126Conditions 1, 2, 3 and 6 indicate that there is not a valid collision 127this frame and you therefore can abort before performing the rest of 128the calculations. In effect, you discard this pair of objects since a 129collision didn't take place. 130 131Ideally, condition 4 should not occur. Whether or not it does occur 132depends on whether or not you handle multiple collisions in one frame. 133If you don't test for condition 4 then the rest of the math works out 134that the balls will remain locked together "arm-in-arm" so to speak. 135 136--------------------------------------------------------------------- 137 3) Calculate the angle of collision vs the velocity vector 138 139In order to calculate the momentum transfer later on we need to perform 140the remainder of these steps on both objects. 141 142At first glance it appears that you simply take the angle between the 143paths of the balls. That doesn't work. Let's take the example of two 144balls headed in the same direction and one ball is catching up on the 145other. If their centers lie on the same line then it's a simple 1D 146collision. But if the center of one ball is offset a little to one 147side then the momentum transfer occurs at an angle even though the 148motion paths are parallel. (See figures 3a and 3b) 149 150What we need to find is the angle formed by the velocity vector and the 151line connecting the centers. We need this angle in order to calculate 152how much of the velocity vector to apply to the collision. In other 153words, if the balls hit head-on, as in figure 3a, then the entire 154velocity vector is applied to the collision. If the balls just nick 155each other, as in figure 3b, then less momentum is transfered between 156the balls. 157 158The mathmatical tool for this problem is the Law of Cosines. 159 a^2 = b^2 + c^2 - 2bc cos(A). 160As written, it's intended for finding the length of a side when an 161angle is known, but we can flip it around: 162 cos(A) = ( a^2 - b^2 - c^2 ) / (-2bc) 163 164 Thus the angle is: A = acos( ( a^2 - b^2 - c^2 ) / (-2bc) ) 165 166Note that we can't use "simple" trig since we're not guaranteed of 167having a right angle. (See figure 3c and 3d) This way you won't have 168to transform coords to some artificial origin. 169 170(-2bc) approaches 0 if and only if the radii of both objects approach 1710. That's a pretty obvious should-not-occur situation. 172 173--------------------------------------------------------------------- 174 4) Calculate portion of velocity vector that applies to collision 175 176Once we have angle A this part turns out to be trivial. The piece of 177the total velocity vector that points toward Ball 2 is: 178 vi=cos(A)*sqrt(dx1^2+dy1^2) 179 180One obvious optimization is to save and use cos(A) above, rather than 181find A only to immediately take its cos() again. 182 183--------------------------------------------------------------------- 184 5) Calculate final velocities along collision vector 185 186At this point we can treat the this as a 1D collision along the line 187connecting the centers. You can find the momentum transfer equations 188in most first-year college physics texts. 189 190 vf1=(((m1-m2)*vi1)+(((1.0+(e1*e2))*m2)*vi2))/(m1+m2); 191 vf2=((((1.0+(e1*e2))*m1)*vi1)+((m2-m1)*vi2))/(m1+m2); 192 193Where: vf1, vf2 - final velocities along collision vector 194 vi1, vi2 - initial velocities along collision vector 195 m1, m2 - mass of each ball 196 e1, e2 - elasticity of each ball 197 198--------------------------------------------------------------------- 199 6) Apply final velocities back to the object 200 201Now we need to subtract the off old velocity vector and add on the new 202one. That will leave us with an object that's moving at the new, 203adjusted speed after ricochet. 204 205 angle=atan2(dcy,dcx); // angle of the line connecting the centers 206 sina=sin(angle); cosa=cos(angle); 207 odx=cosa*vi; // subtract off old velocity vector 208 ody=sina*vi; 209 ndx=cosa*vf1; // add on new velocity vector 210 ndy=sina*vf1; 211 dx+=odx-ndx; // signs look reversed but are correct 212 dy+=ody-ndy; 213 214--------------------------------------------------------------------- 215 So, that's a ricochet 216 217So, that's how you ricochet two balls. Whew! It seems like a lot of 218work, but there's no magic involved. Just break the problem into 219pieces and use the appropriate tool for each piece. 220 221We haven't discussed optimizations, yet. It turns out, collisions 222happen rarely enough that even using floating point and transcendental 223functions like sin and cos don't slow things down noticable. For 224example, an Asteroids clone with 30-40 rocks bouncing around spends 225almost all its time blting the sprites to the screen. The time to 226calculate ricochets is completely swamped. Still, for maximum speed 227you'll want to use a fixed-point representation and lookup tables for 228the transcendentals. 229 230But my advice is to live with floats while you build your prototype. 231The first rule of optimization: Make it right before you make it faster. 232 233Our implementation uses a dx, dy method to move the balls. An 234angle/norm implementation would perform the same work, it's just 235arranged a little different. See CBENCH.ZIP for a dx/dy implementation 236by David Bollinger and CAROM.ZIP for an angle/norm implementation by 237Csaba Markus. 238 239--------------------------------------------------------------------- 240 Wall collisions 241 242At the time of this writing, we haven't completed the implementation of 243wall collisions. 244 245Our first pass implies that the trick to finding the collision point is 246to calculate a "shadow wall" one radius distance to each side of the 247wall. Then, simply find the intersection of the path of the center of 248the ball with each shadow wall (see figure 4a). Find which is closer to 249the original location of the ball. 250 251That gives you a possible collision. Next, you need to decide if the 252ball actually hit the wall face, or if it passed beyond the end of the 253wall and possibly hit the endpoint. 254 255To find if the ball hit a wall face, find the distance from the center 256of the ball to each endpoint of the shadow wall. If either distance is 257greater that the distance from one endpoint to the other then the 258center missed the wall face. 259 260To find if the ball hit the endpoint of a wall, treat the wall endpoint 261as an infinitely massive ball of zero size and go through the ball 262collision above (see figure 4b). 263 264--------------------------------------------------------------------- 265 Simultaneous collisions 266 267Again, we haven't implemented this yet. There are two likely 268candidates for this. 269 270First, go through each pair of objects and find the pair lowest time of 271collision. Perform that collision and then find the next lowest time, 272taking into account the new velocities of the objects. 273 274Or, sort the times and step through them in that order. Resort all 275objects that are close enough to be affected by each collision as they 276happen. 277 278--------------------------------------------------------------------- 279 Wrapping it up 280 281I hope you found this description useful. I realize it's ended up a bit 282on the terse side. Hopefully the PCX files will help you visualize what 283I'm trying to describe. If anyone has questions, feedback, suggestions or 284critique please feel free to contact me, Drake Christensen 71251,433. 285 286This file owes its existence to David Bollinger 72510,3623. He and I 287spent over a month brainstorming this surprizingly obscure problem in the 288GAMDEV forum on Compuserve. His CBENCH example is available in GAMDEV. 289Obviously, any mistakes or obfuscation in this text are entirely my fault. 290 291Another who provided needed assistance is Csaba Markus (E-mail: 292ethcms@duna.ericsson.se). We found his CAROM simulator at just the right 293time to convince ourselves that we were heading down (one of) the right 294path. 295 296I can't give a specific bibliography, but if you want to research this in 297texts, my suggestion is to visit a local college library and look for 298mechanics and physics texts circa 1910 or so. I was unable to find 299anything more recent than those. Apparently, the academic community 300doesn't consider this an interesting subject anymore. :-) 301 302Related files: 303 CBENCH.ZIP - Collision test bench by David Bollinger 72510,3623 304 CAROM.ZIP - Carom simulator by Csaba Markus ethcms@duna.ericsson.se 305 CLDTHD.ZIP - Thread on collision physics by (mostly) David Bollinger 306 and Drake Christensen

[/CODE]

_______________________
[Insert signature here]

Mark Venture
Member #1,272
April 2001
avatar

The following code calculates a smooth path towards a target :

1 
2ball_x = the ball's x position
3ball_y = the ball's y position
4 
5target_x = the ball's target x
6target_y = the ball's target y
7 
8dx = abs(ball_x - target_x)
9dy = abs(ball_y - target_y)
10 
11dirx = sign(ball_x - target_x)
12diry = sign(ball_y - target_y)
13 
14cx = 0
15cy = 0
16 
17cx = cx + dx
18if (cx >= dy)
19{
20 ball_x += dirx;
21 cx -= dy;
22}
23 
24cy = cy + dy
25if (cy >= dx)
26{
27 ball_y += diry;
28 cy -= dx;
29}

so the problem becomes finding a good target_x, target_y :

target_x = ball_x + cos(angle) * radius
target_y = ball_y - sin(angle) * radius

angle is in radians (from 0 to 2*PI). Radius can be any number; it is just needed to calculate target_x, target_y

for a breakout-style game you need to calculate the angle from the distance of ball_x to pad's center. The more to the side the ball hits the pad, the highest angle the ball should take.

You can also use this algorithm for bullets in a shoot-em-up to target the player's sprite.

(if it does not work it means I don't remember the algorithm exactly, but I 've done it in my breakout game)

"as long as there is hope, we will fight" (quote by Captain Avatar, Star Blazers, Season 1)

almeidaj
Member #1,951
February 2002

Aren't we all forgetting the padle influence on the ball angle and velocity, when the ball colides with a padle in movement... :-/

Thomas Harte
Member #33
April 2000
avatar

You mean the fact that at the point of collision there is actually a force perpendicular to the collision and you assume the bat's surface has a non-zero friction coefficient?

Indeed, under those circumstances, even if you are doing the most common thing and modelling your collisions as instantaneous, when the ball hits the bat, the bat will excert a force as you describe. The trick is to remember that the law of conservation of momentum works 'in both directions' (i.e. parallel and perpendicular, or for a simple game, x & y).

Go to: