Archived

This topic is now archived and is closed to further replies.

mickey

help plz.., breakout/arkanoid clone, bouncing ball, giving it angles etc.,

Recommended Posts

if you can, plz explain it very simple, i have a velocity for the ball, plus position and to bounce it, i do it the most simplest way., // this is how i move the ball ballpos += ballvelocity * elapsed time // and this how i bounce the ball against the wall and paddle check for collision against wall if true then { ballvelocity *= -1.0f; set ball position next to the object } check collision again paddles leftarea, rightarea and middle area, then same method as above, i make the velocitiy negative., okey my problem here is, the bounce on the paddle would be wrong because it would just bounce back where it came from, it should bounce on in a new direction, also, how would i go by giving the angle i desire for the ball? also, how do i know exactly on what spot on the paddle did the ball hit it? btw, am using x and z axis for this, i use bounding volumes for the collision detection and D3DXVECTOR3 for the positions and velocities., do i need an acceleration? if so, how will i use it? many thanks, [edited by - mickey on August 11, 2002 10:01:13 AM]

Share this post


Link to post
Share on other sites
hmm., how will i know, if the ball came from the left side, or the right side of the game area? so i can bounce the ball appropriately,

ie, if the ball came from the left side, and it hits the left area of the paddle, then bounce it back where it came from,

if the ball came from the right side, and it hits the left area of the paddle, then bounce it to the left side of the game area,

thanks!!

Share this post


Link to post
Share on other sites

  
bool ballcollidesleftpaddle();
bool ballcollidesrightpaddle();

static vec2 absvelocity(2,2); // just some values, could be choosen by the user..


if(ballcollidesleftpaddle()) {
ball.velocity.x = asbvelocity.x; //positive velocity => right

} else if(ballcollidesrightpaddle()) {
ball.velocity.x = -asbvelocity.x; //negative velocity => left

}

if(ballcollidestop()) {
ball.velocity.y = absvelocity.y; //positive velocity => down

} else if(ballcollidesbottom()) {
ball.velocity.y = -absvelocity.y; //negative velocity => up

}


"take a look around" - limp bizkit
www.google.com

Share this post


Link to post
Share on other sites
yes, that''s what i do right now, but after a while, the game looks silly, i want to specify the amount of angle that the ball would take when it hits the paddle,

thanks,

Share this post


Link to post
Share on other sites
Think of it this way..

If a ball moving at (-1,-1) hits a horizontal surface, then only the Y axis of the ball''s movement vector should be reflected, right? If the ball hits a vertical surface, then only the X axis of the ball''s movement vector should be reflected, right?

So... if you hit the roof or the paddle, multiply the ball-move-vector''s Y axis by -1, but leave the X alone. If you hit the side walls, ball-move-vector''s X axis gets reversed, but the Y gets left alone.

Or, for maximum flexibility... take the surface normal of the surface the ball hit. Call this vector SurfNorm, and call the ball''s movement vector BallMove.

BallMove.x += (-2*BallMove.x) * SurfNorm.x;
BallMove.y += (-2*BallMove.y) * SurfNorm.y;

Remember that the surface normals should be facing into the playing field (or out of the solid object they represent the sides of), and you should get this down pat with no problems at all.

The left wall has a surface normal of (1,0), while the right wall has a normal of (-1,0). The paddle''s top surface has a surface normal of (0, -1), and the roof has a surface normal of (0, 1) (if positive Y represents up)

You''ll actually need more complex math to do real reflection, but this is just a quick fix for you...

(Pardon... just re-read your original post. Replace all the Ys in my post with Zs)

Share this post


Link to post
Share on other sites
I made a game called Breakanoid a while ago. I came up with some algorithm for the paddle stuff:

// -1 for absolute left of paddle, 0 for middle, +1 for absolute right
fPaddleHit = (pBall->fCurrentX - this->fPaddleHPosX) / this->fPaddleHSize * (float)0.9;
// Our angle of attack
fAngleIn = atan2f(-pBall->fSrcSpeedX, pBall->fSrcSpeedY);
// Calculate our defence angle
fAngleOut = fPaddleHit * ((float)(PI / 2) + fAngleIn * (fPaddleHit < 0 ? -1 : 1)) - fAngleIn;
// Calculate speed vector based on our outgoing angle
pBall->fSrcSpeedX = -pBall->fSrcSpeed * sinf(fAngleOut + (float)(PI));
pBall->fSrcSpeedY = -pBall->fSrcSpeed * cosf(fAngleOut);


Right from the source. Please dont make me explain it...

Share this post


Link to post
Share on other sites
ehm., okey, can somebody else plz explain what happened there? what''s with the angle in and angle out? and what does he mean by " Calculate speed vector based on our outgoing angle "?

many thanks,

Share this post


Link to post
Share on other sites
Ok, I don't remember exactly here, but I'll try to explain.

The effect I wanted was that the ball should go out in "same" angle as it came in when it hit the middle of the paddle, and have the angle increase or decrease based on how far away from the middle it hit.

Let's say we have the ball coming in with the speed vector (2,1). If it hits in the middle, it should go out with the speed vector (2,-1). With me? In my algorithm the ball would bounce out with the speed vector (-2,-1) -- the same -- if it would hit the absolute left of the paddle, and bound out with a zero angle if it hit the absolute right. I then interpolate between these cases.

This is pretty easy to implement, if you know your trigonometry. My solution is messy and tweaked, so you should better try to do it yourself. Just pick up pen and paper and draw it.
The point is first to get where on the paddle the ball hit (fPaddleHit): -1 (left) to 0 (middle) to 1 (right). I multiplied this by 0.9 cus I didn't want the ball to go out completly horizontal.
Then you must calculate what angle the ball hit the paddle (fAngleIn). This angle should be calculated so that it be: -PI/2 (from left) to 0 (from above) to +PI/2 (from right).

Hell! I can't explain this. My calculations are very messy and tweaked to work. If anyone else understand what I'm doing and can explain it, please do!

The "Calculate speed vector based on our outgoing angle" is just what it says. fAngleOut is our outgoing angle, which we convert to the speed vector I use to move the ball. You should have something similar, right? It is as simple as it is in my source, except that you might not need the " + (float)(PI)" part.

[edited by - CWizard on August 13, 2002 1:00:08 PM]

Share this post


Link to post
Share on other sites
wow, thanks a lot CWizard! that''s actually the effect that i want, increasing the angle based on how far it hits the paddle from the middle!

will be back in 3 days if ever i won''t get this right, hope you''re still there,

thanks again,

Share this post


Link to post
Share on other sites
atan() is inverted tan, atan2() is a nice if you don''t want to risk a division by zero, and still get correct angle. Check here: http://www.introl.com/introl-demo/Libraries/C/ANSI_C/math/atan2.html.

I think you should try to come up with how "my" algorithm work on your own, and then you can look on my code for inspiration on how to implement it; I think you need to understand it to get it working in your engine.

Share this post


Link to post
Share on other sites
The ''f'' in atan2f() is for the (32-bit) float version of the function, which is otherwise double. As I''m only using floats here I always use sinf(), cosf(), atan2f() etc.

Share this post


Link to post
Share on other sites
hello, i think i''ve done it, with your help and a little more help from other tutorials.., i think i''ve understood it,

x/y = length * sin/cos // this will give you your desire angle, they say, this is from polar coords to cartesian coords,

anyway, i''ve a new problem hope you could help me out here too. I''ve done all sorts of collision detection between the ball and the block, my only problem left now is, sometimes the ball gets stuck in the block or i have a block that needs to be hit thrice before it breaks, but sometimes the ball just hit it once and it breaks, i don''t know if the problem here is that my computer is fast or probably the speed of the ball., any ideas how to improve it?

btw, my loop goes like this,

check collision
moveball

maybe i should interchange those two huh?

thanks,

Share this post


Link to post
Share on other sites
Hm. In my version, I meant to implement a very sophisticated collision detection, where each time the ball starts going somewhere it calculates when (in time) it would hit anything, and where it should go from there. Then in my loop, I just checked if that time had been reached, and if so, I took the destination action.
This worked well for the borders, and for when the ball hit the brick on its sides, but I never came up with a good algorithm to detect when and how the ball would hit the corner. Due to this, I had to implement a real time collision detection as well. I think that the most important is to not only check the ball's position, but also its vector when detecting a hit.

A small excerpt from my code:
    
// Are we in the middle of a brick? No idea what to do...

if(this->pcBrickType[nBrickHit = nBrick])
nTypeOfHit = 0x80 | 0x02 | 0x04 | 0x10;

// Hitting a brick X - 1?

else if(this->pcBrickType[nBrickHit = nBrick - 1] && fLocalX < pBall->fRadius && pBall->fSrcSpeedX < 0)
nTypeOfHit = 0x80 | 0x01 | 0x02 | 0x10;

// Hitting a brick X + 1?

else if(this->pcBrickType[nBrickHit = nBrick + 1] && fLocalX > 1 - pBall->fRadius && pBall->fSrcSpeedX > 0)
nTypeOfHit = 0x80 | 0x01 | 0x02 | 0x10;

// Hitting a brick Y - 1?

else if(this->pcBrickType[nBrickHit = nBrick - this->nBoardWidth] && fLocalY < pBall->fRadius && pBall->fSrcSpeedY < 0)
nTypeOfHit = 0x80 | 0x00 | 0x04 | 0x10;

// Hitting a brick Y + 1?

else if(this->pcBrickType[nBrickHit = nBrick + this->nBoardWidth] && fLocalY > 0.5 - pBall->fRadius && pBall->fSrcSpeedY > 0)
nTypeOfHit = 0x80 | 0x00 | 0x04 | 0x10;

// Are we hitting paddle?

else if(pBall->fCurrentY > (float)this->nBoardHeight / 2 - 0.5 - pBall->fRadius
&& pBall->fSrcSpeedY > 0
&& pBall->fCurrentX > this->fPaddleHPosX - this->fPaddleHSize
&& pBall->fCurrentX < this->fPaddleHPosX + this->fPaddleHSize) {
nTypeOfHit = 0x80;
// -1 for absolute left of paddle, 0 for middle, +1 for absolute right

fPaddleHit = (pBall->fCurrentX - this->fPaddleHPosX) / this->fPaddleHSize * (float)0.9;
// Our angle of attack

fAngleIn = atan2f(-pBall->fSrcSpeedX, pBall->fSrcSpeedY);
// Calculate our defence angle

fAngleOut = fPaddleHit * ((float)(PI / 2) + fAngleIn * (fPaddleHit < 0 ? -1 : 1)) - fAngleIn;
// Calculate speed vector based on our outgoing angle

pBall->fSrcSpeedX = -pBall->fSrcSpeed * sinf(fAngleOut + (float)(PI));
pBall->fSrcSpeedY = -pBall->fSrcSpeed * cosf(fAngleOut);
}

// If no hit, we'll leave it here

if(!nTypeOfHit) return false;

// Adjust angles etc.

pBall->fDestX = pBall->fCurrentX;
pBall->fDestY = pBall->fCurrentY;
pBall->fDestSpeed = pBall->fSrcSpeed;
pBall->fDestSpeedX = (nTypeOfHit & 0x02) ? -pBall->fSrcSpeedX : pBall->fSrcSpeedX;
pBall->fDestSpeedY = (nTypeOfHit & 0x04) ? -pBall->fSrcSpeedY : pBall->fSrcSpeedY;
pBall->fDestAngle = atan2f(pBall->fDestSpeedX, pBall->fDestSpeedY);

// If we hit a brick, take care of it

if(nTypeOfHit & 0x10) this->HitBrick(nBrickHit);

As you see. When I check if the ball hits the right side of the brick to the left "brick space" the ball is in, I only raise a hit if the ball's X-vector is negative. I flag this as "vertical hit" and then negates the X-vector, and so it won't detect a hit next time. I do not properly handle when the ball find itself right inside a brick (that is, its center is inside a brick), but that should never happen.

I could mention, that I'm using a virtual coordinate system in my game, where each brick is 1.0 units wide and 0.5 units high. And use two arrays of chars[BoardWidth * BoardHeight] (note, not [BoardWidth][BoardHeight]), one for the type of brick, pcBrickType[] (also indicating if there is any brick), and one for the status of that brick, pcBrickStatus[] (which is not used here). Also note, that my game isn't finished, so the code above isn't perfect.

fLocalX and fLocalY are floats with the values 0.0-1.0 and 0.0-0.5, respectivly, indicating where in the "brick space" the ball is. nBrick is the index in the array where the ball is in.

[edited by - CWizard on August 18, 2002 12:03:25 PM]

Share this post


Link to post
Share on other sites
helo,

ehm, what do you mean by this "but also its vector when detecting a hit", what kind of vector am i going to watch out for this?

also, do you set the position too of the ball after it hits or you just bounce it back with the appropriate angle?

i used a 3 array of int for my game, ie, map[width][height][type of block] then seperate meshes for each type of block i have but all the block''s texture is only contained in one file. This way, i don''t need to call SetTexture everytime i render a block but instead, use the right mesh(the only thing that is different are the texture coordinates), how about you? are you using d3d8 too?

Share this post


Link to post
Share on other sites
hmm.., "where each time the ball starts going somewhere it calculates when (in time) it would hit anything", do you think i need to do this too so that my ball doens''t stuck in the blocks or goes out of bounds? yeah, sometimes my ball just go out of bounds, it doesn''t bounce properly when it hits the sides of the wall,

Share this post


Link to post
Share on other sites
argh! halp!

maybe it has got to do with my blocks having round sides(i used a box, attached 2 cylinders unto it''s side), everything is smooth as long as the ball hits the bottom, top and sides of the blocks, but when it comes to the corners, the ball would either slide through or get stuck inside. Maybe this has something to do with the ball moving so fast?

or maybe my checking is bad? pls look at how i do it,

if(ballposZ + min/max >= blocksposZ + min/max && ballposz + min/max <= blockPosZ + min/max)
// possible collision, now check x
if(ballposX + min/max >= blockPosX + min/max && ballposX + min/max <= blockposX + min/max)
// collision detected
bounce ball


Share this post


Link to post
Share on other sites
quote:
Original post by mickey
ehm, what do you mean by this "but also its vector when detecting a hit", what kind of vector am i going to watch out for this?
This was the ball''s vector. What I mean is this: If the ball is "in" or "at" the left border, you should only detect a hit when the ball''s vector has a negative X-part (ie. travelling left), and not if it is positive (ie. travelling right). Make sense? This is to avoid race conditions, when the ball gets a bit stuck in the wall or brick, and continue bouncing back and forth. Just think about it; If your ball is "inside" the left border, and is travelling right, you don''t want it to change direction to the left.
quote:
also, do you set the position too of the ball after it hits or you just bounce it back with the appropriate angle?
Eh, in my current case: no. Well, usually it do, as I have a hybrid system for collission detection. When the hit is predicted (and it didn''t hit anything else before that) it will be moved to exactly the radius from the brick wall (and on it''s path towards it), while on a "real time" hit (the stuff I''ve shown here) it won''t be adjusted, only the speed vector changes.
quote:
i used a 3 array of int for my game, ie, map[width][height][type of block] then seperate meshes for each type of block i have but all the block''s texture is only contained in one file. This way, i don''t need to call SetTexture everytime i render a block but instead, use the right mesh(the only thing that is different are the texture coordinates), how about you? are you using d3d8 too?
Sorry to say, I don''t quite understand why you need a three dimensional array or how you use it, but that''s up to you, and I guess it''s working. No, I didn''t use Direct3D, just DirectDraw 7. The stuff I made was mostly to try a kind of game state machine with independent objects that I plan to employ in the future, so it was never really meant to be a "real" game.
quote:
hmm.., "where each time the ball starts going somewhere it calculates when (in time) it would hit anything", do you think i need to do this too so that my ball doens''t stuck in the blocks or goes out of bounds? yeah, sometimes my ball just go out of bounds, it doesn''t bounce properly when it hits the sides of the wall,
Well, I wouldn''t suggest it. I think it works really great in my game (at least for the borders ), but I think it would be a pain in the ass to implement it at this stage. As you might have seen in my code, I keep both source and destination status of ball. And I do not increment the balls position, but calculate it exactly from where it''s source position was, it''s "source" speed vector and the time elapsed since it departed from that source point. I couldn''t make this collision prediction complete, so I also implemented convensional detection as back-up, but then the prediction isn''t really needed any more. I think you should build on what you have, instead of starting all over.

I''m very unsure about your code in your latest post, as I''m tired (haven''t slept for 27 hours ), and I will have a look at after some sleep and see if I can make a constructive comment. Perhaps I will understand it directly after a slept, but know I can''t figure out what the min/max is for...

Share this post


Link to post
Share on other sites
hello CWizard,

thanks you very much for sparing your time helping me out,

heh, sorry about the ball''s vector, yeah i understand that i also use that kind of method.

i constructed a bounding volumes for all the objects in my game using D3DX so that''s what min/max is for.,

anyway, i almost understand now., one thing left bothers me., atan2f() is used to calculate the angle in which the ball hits the paddle., how could that be used for the next angle?? i mean, the angleout would be calculated "on which part" of the paddle the ball would hit it, so the anglein of the ball doesn''t matter.., or in short, i didn''t understand this code, "fAngleOut = fPaddleHit * ((float)(PI / 2) + fAngleIn * (fPaddleHit < 0 ? -1 : 1)) - fAngleIn"

and last., my ball still gets stuck in the blocks., i''ve observed that, evertime my ball hits near the corners of my rounded shape blocks, it get''s stuck, otherwise, no. (ie, top/bottom and sides),

again, thanks very much for your patient CWizard, hope you could hang-on am almost there!

Share this post


Link to post
Share on other sites
Let''s say the ball is heading for the paddle (vector +9.4, +3.4), that atan will tell us is about 0.35 * PI (20 degrees). Even if we are modifying the angle, we''ll want the ball out with at -0.35 * PI or 1.9 * PI (20 or 340 degrees) (vector +9.4, -3.4), if the ball hit the middle. This is excatly like we hit the top of a normal brick. I then want this angle to change based on how far (in per cent) I hit off the middle.
I do this by calculating the fAngleIn = atan2f(-X,Y), which gives us -70 degrees, that is, I rotate it 90 degrees. In the middle case, all that is done is to negate this angle (ie. +70 degrees), which is then turned back into a vector.
In my formula, if we are hitting the absolute right of the paddle with fAngleIn = -70 degrees, the fAngle out will be 1 * 0.9 * 90 = 81 degrees, if we hit at 75% of the paddle it will be interpolated between 70 (middle) and 81 (absolute right).

Lets look at the formula again (it''s bad and messy, I know):

fAngleOut = fPaddleHit * ((float)(PI / 2) + fAngleIn * (fPaddleHit < 0 ? -1 : 1)) - fAngleIn;

fPaddleHit * ((float)(PI / 2) will 0 when hitting the middle, 0 -> -45 when left on the paddle, and 0 -> +45 when hitting on the right. I then add the fAngleIn, which is negated if hit on the left, and I then the the in angle off that again. No idea how this formula works, but it does the trick somehow. If it is coming from the right (-90 << fAngleIn << 0), the possible out angle is between the reverse in-angle and 90 degrees (-70 through 90 in our case). If it comes from the left (0 >> fAngleIn >> 90) it can come out between -90 and the reverse in angle (-90 through 70 in our case). Hope you understand anything here, I bet I wouldn''t.

For you problem with the collission detection, I''m afraid I really don''t know where to look. Almost all people making a Arkanoid/Breakout or Pong clone seem to have problem with the ball getting stuck. I did not have that problem at all, so I lack the experience to fix it. Perhaps you need to redo the algorithm from scratch, sometimes that can help. There is another thread here just now (or some hours ago) discussing this problem, see if they have anything good. Also try to search the archives, might give you some hints.

Share this post


Link to post
Share on other sites
Hiya CWizard, thanks very much, i think you have explained enough, it''s upto me now to understand what you just explained when i go back to my code, thanks again for having some time to help me out,

Share this post


Link to post
Share on other sites
hello,

hope you''re still there to see this, anyway, i''ve got a different question now,

do you have animation on your breakout game like when a ball hits a block and thus your block will show a breaking apart animation.. i was wondering if you associated a ''timer'' for each of the blocks. If not, then plz share how your architect your animations in your breakout clone.

many thanks,

Share this post


Link to post
Share on other sites
Sorry, I didn''t come to that point; they simply disappear

But if you want to animate them, you''ll need some sort of timer for every block. I had this in mind when I designed my game, so I had several parallell arrays, which held different kind of info for every block. The only one I used, though, was my BrickType, which simply said of which type the brick was, if any. Another one I planned on using was BrickStatus, which could hold a counter for bricks that needed more than one. For animation another one would be needed. You''ll be better off, if you somehow store that the brick shall animate, and store the time when it begins, rather then keep a "live" counter on each brick. When rendering, and come across such a brick, you just calculate how much time has passed since it started and pick the correct frame in the animation.

I have a common timing technique when I make "game objects", in that I have initialization, control, run, and render methods. The run methods increments the objects internal timer, which cause the "game object" to pause if I do not call a run method. Which makes pausing the game rather easy, and you can also run it faster and slower, without modifying anything of the object. To have an internal timer for your "game object" is highly suggested to use as reference for the animations, rather than, for example, the system timer.

Just some thoughts, good luck

Share this post


Link to post
Share on other sites