Advertisement

Problems With Ball Bouncing

Started by April 22, 2001 09:57 PM
4 comments, last by mmarvi 23 years, 9 months ago
I am writing a table hockey-style game, and I''m having trouble writing code for the ball to bounce off the rectangular bat. The code I have so far is below: // Handle ball collisions bx = Ball->m_PosX; by = Ball->m_PosY; dx = Ball->m_VelX; dy = Ball->m_VelY; if (by > 457 || by < 54) { dy = -dy; } if (Ball->SpriteHit(Player1)) { dy = -dy; } bx += dx; by += dy; Ball->SetVel(dx, dy); Ball->SetPos(bx, by); FYI, bx and by are the coordinates for the position of the ball, and dx and dy are the velocity of the ball. The rectangular bat is 76x15 in size, the ball is 19x19, and the ball''s original velocity is (0,4). Player1 is the sprite object for the bat. The problem I''m having is that if you move the bat towards the ball, the ball goes "under" the bat and "shakes" a little until you move the bat again.
The correct physics way to model reflection (assuming an ideal suface of course) is that the angle of reflection is equal to the angle of incidence on the opposite side of the line normal to the surface. What does that mean? Imagine you have your flat surface, the bat, and it is a 180 degree angle. The 90 degree mark is the line normal to the surface. If your ball comes in at 15 degrees it should be reflected at the same angle, on the oppsite side of the normal line, so it should bounce back at 165 degrees (180-15 degrees). If it comes in at 105 degrees it should bounce back at 75 degrees (180-105 degrees). Etc, etc. Note that if it comes in at 90 degrees, it should bounce straight back. For more realistic motion, you should add part of the velocity (if any) of the colliding surface to the ball too. This way, if you bat is moving side ways when it collides with the ball, it will impart some sideways velocity to the ball. You can model this more accurately if you add mass values to the objects so that you can compute the momentum, but that is probably over kill. As for the collision detection, if the ball goes "under" the bat, it seend that the velocity of the two may be so great that they are jumping past each other with out ever colliding. You need to make sure that when you check for collisions, you check whether or not the ball would have passsed through were the bat will pass through, or else limit the velocities so they can never leap over each other.
Advertisement
in;
  if (Ball->SpriteHit(Player1)){   dy = -dy;}  

should''nt you have dx = -dx. No?
This is the kind of collision detection I used in my game. It''s not the best but it can be correct for a first game

You''re problem is that the only thing you verify is if the ball is under the bat but you don''t know if the ball is going toward the bat or not. After the collision, your ball must have a velocity high enough to make sure it escapes the bat or else, the speed is inversed again and it "shakes". You have two solution : you increase the speed or you check the direction of the velocity every time you check for a collision.
alexk7
Let me clarify myself. The problem I''m having is that if the bat "runs over" the ball, this is when the ball gets stuck under the bat and "shakes" until either it gets out, or you move the bat. Also, with what invective said, can anyone post code for a bouncing algorithm that is just sophisticated enough for this type of game so that the ball bounces off at the right angle?
Ok, the simple (if not particularlly efficient) solution to the bounce over problem: let your object move only in one pixel increments. Instead of just adding a value to the x and y coordinates and then checking the values, call a move function that interpolates between the current position and the target position in one pixel increments. At each increment, check for and handle a collision. This lets you get past the problem of skipping pixels. The only question you will have is of course how do I interpolate between coordinates? Use Bresenham's line algorithm to iteratively generate your coordinates (its normally used to draw lines, but what you need here is all the coordinates along a line from one your start point to your destination). Well now you need a copy of Bresenham's algorithm. Easy, i just checked google and it came up with tons of them. Here's and example:
    void BresenhamMoveTo(int startx, int starty, int destx, int desty) {        int dy = desty - starty;        int dx = destx - startx;        int stepx, stepy;        if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }        if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }        dy <<= 1;                                              // dy is now 2*dy        dx <<= 1;                                              // dx is now 2*dx        CheckForCollision (startx, starty);        if (dx > dy) {            int fraction = dy - (dx >> 1);                     // same as 2*dy - dx            while (startx != destx) {                if (fraction >= 0) {                    starty += stepy;                    fraction -= dx;                            // same as fraction -= 2*dx                }                startx += stepx;                fraction += dy;                                // same as fraction -= 2*dy                CheckForCollision (startx, starty);            }        } else {            int fraction = dx - (dy >> 1);            while (starty != desty) {                if (fraction >= 0) {                    startx += stepx;                    fraction -= dy;                }                starty += stepy;                fraction += dx;                CheckForCollision (startx, starty);            }        }    }    

As for how to implement the reflection algorithm in my last post, that depends on where your objects are in relation to one another. If you are wondering how to get the angle, it is given by the triangle formed by your velocity vectors. you can compute the hypotenuse of the third side as sqrt(dx*dx + dy*dy). angle = arccosine (dx/hyp) or arcsine (dy/hyp). Draw it out and it may make more sense, as long as you remeber your trig. I wish I had time to give you code, buts is 1 am and i should be sleeping!

ONE POINT I FORGOT: Don't keep handling the same old collision over and over again!!! maybe you want to break out of the move when you hit a collision, or else move the colliding object away before continuing.

Edited by - invective on April 24, 2001 4:20:50 AM

This topic is closed to new replies.

Advertisement