11 Replies Latest reply on Jan 23, 2010 5:27 AM by 843853

    Slime Volleyball physics ball movement

    843853
      Hi, I was wondering if anyone could explain wedgey's slime volleyball code to me. just the MoveBall() is quite confusing:

      private void MoveBall()
      {
      int fudge = 5; // was 5. a fudge factor.
      int maxXV = 15; // was 15
      int maxYV = 22; // was 22

      // move the ball
      ballY += --ballVY;
      ballX += ballVX;

      // collision detection
      if(!fEndGame) {
      int dx = 2*(ballX-p1X);
      int dy = ballY-p1Y;
      int dist = (int)Math.sqrt(dx*dx+dy*dy);
      int dvx = ballVX-p1XV;
      int dvy = ballVY-p1YV;
      if(dy > 0 && dist < p1Diam+ballRad && dist > fudge) {
      /* i have nfi what this is. i'm supposed to have done engineering
      dynamics and i can't remember any equation with x*x'+y*y' in it...
      it was a long time ago! - wedgey */
      int something = (dx*dvx+dy*dvy)/dist;
      ballX = p1X+(p1Diam+ballRad)/2*dx/dist;
      ballY = p1Y+(p1Diam+ballRad)*dy/dist;
      // cap the velocity
      if(something <= 0) {
      ballVX += p1XV-2*dx*something/dist;
      if(ballVX < -maxXV)
      ballVX = -maxXV;
      if(ballVX > maxXV)
      ballVX = maxXV;
      ballVY += p1YV-2*dy*something/dist;
      if(ballVY < -maxYV)
      ballVY = -maxYV;
      if(ballVY > maxYV)
      ballVY = maxYV;
      }
      fP1Touched = true;                    
      }

      // that stuff all over again, but for p2.
      dx = 2*(ballX-p2X);
      dy = ballY-p2Y;
      dist = (int)Math.sqrt(dx*dx+dy*dy);
      dvx = ballVX-p2XV;
      dvy = ballVY-p2YV;
      if(dy > 0 && dist < p2Diam+ballRad && dist > fudge) {
      int something = (dx*dvx+dy*dvy)/dist;
      ballX = p2X+(p2Diam+ballRad)/2*dx/dist;
      ballY = p2Y+(p2Diam+ballRad)*dy/dist;
      if(something <= 0) {
      ballVX += p2XV-2*dx*something/dist;
      if(ballVX < -maxXV)
      ballVX = -maxXV;
      if(ballVX > maxXV)
      ballVX = maxXV;
      ballVY += p2YV-2*dy*something/dist;
      if(ballVY < -maxYV)
      ballVY = -maxYV;
      if(ballVY > maxYV)
      ballVY = maxYV;
      }
      fP2Touched = true;
      }
      // hits left wall
      if(ballX < 15) {
      ballX = 15;
      ballVX = -ballVX;
      }
      // hits right wall
      if(ballX > 985) {
      ballX = 985;
      ballVX = -ballVX;
      }
      // hits the post
      if(ballX > 480 && ballX < 520 && ballY < 140)
                     {
      // bounces off top of net
      if(ballVY < 0 && ballY > 130) {
      ballVY *= -1;
      ballY = 130;
      } else if(ballX < 500) { // hits side of net
      ballX = 480;
      ballVX = ballVX >= 0 ? -ballVX : ballVX;
      } else {
      ballX = 520;
      ballVX = ballVX <= 0 ? -ballVX : ballVX;
      }
                     }
      }

                // clear the ball position
                int ballXPix = ballOldX*nWidth/1000;
      int ballYPix = 4*nHeight/5-ballOldY*nHeight/1000;
                int ballRadPix = (ballRad+fudge)*nHeight/1000;
                // clear the old ball position
                screen.setColor(Color.blue);
                screen.fillRect(ballXPix-ballRadPix, ballYPix-ballRadPix, 2*ballRadPix, 2*ballRadPix);
           }

      thanks
      btw, the entire code can be found at the link [ http://oneslime.net/two/Slime2P.java].

      Edited by: Slimer3 on Jan 20, 2010 7:58 PM
        • 1. Re: Slime Volleyball physics ball movement
          843853
          You're asking people to fish though code that you don't understand, the very least you could do is have the considerations to post it using code tags. As it stands you're post is corrupt: see the bold black lettering, that is the forum software interpreting letter combinations as formatting characters. Please post the code again and use the formatting tags.
          • 2. Re: Slime Volleyball physics ball movement
            843853
            sorry about that. this is my first time with forums.
            private void MoveBall() {
                    int fudge = 5; // was 5. a fudge factor.
                    int maxXV = 15; // was 15
                    int maxYV = 22; // was 22
            
                    // move the ball
                    ballY += --ballVY;
                    ballX += ballVX;
            
                    // collision detection
                    if (!fEndGame) {
                        int dx = 2 * (ballX - p1X);
                        int dy = ballY - p1Y;
                        int dist = (int) Math.sqrt(dx * dx + dy * dy);
                        int dvx = ballVX - p1XV;
                        int dvy = ballVY - p1YV;
                        if (dy > 0 && dist < p1Diam + ballRad && dist > fudge) {
                            /* i have nfi what this is. i'm supposed to have done engineering
                            dynamics and i can't remember any equation with x*x'+y*y' in it...
                            it was a long time ago! - wedgey */
                            int something = (dx * dvx + dy * dvy) / dist;
                            ballX = p1X + (p1Diam + ballRad) / 2 * dx / dist;
                            ballY = p1Y + (p1Diam + ballRad) * dy / dist;
                            // cap the velocity
                            if (something <= 0) {
                                ballVX += p1XV - 2 * dx * something / dist;
                                if (ballVX < -maxXV) {
                                    ballVX = -maxXV;
                                }
                                if (ballVX > maxXV) {
                                    ballVX = maxXV;
                                }
                                ballVY += p1YV - 2 * dy * something / dist;
                                if (ballVY < -maxYV) {
                                    ballVY = -maxYV;
                                }
                                if (ballVY > maxYV) {
                                    ballVY = maxYV;
                                }
                            }
                            fP1Touched = true;
                        }
            
                        // that stuff all over again, but for p2.
                        dx = 2 * (ballX - p2X);
                        dy = ballY - p2Y;
                        dist = (int) Math.sqrt(dx * dx + dy * dy);
                        dvx = ballVX - p2XV;
                        dvy = ballVY - p2YV;
                        if (dy > 0 && dist < p2Diam + ballRad && dist > fudge) {
                            int something = (dx * dvx + dy * dvy) / dist;
                            ballX = p2X + (p2Diam + ballRad) / 2 * dx / dist;
                            ballY = p2Y + (p2Diam + ballRad) * dy / dist;
                            if (something <= 0) {
                                ballVX += p2XV - 2 * dx * something / dist;
                                if (ballVX < -maxXV) {
                                    ballVX = -maxXV;
                                }
                                if (ballVX > maxXV) {
                                    ballVX = maxXV;
                                }
                                ballVY += p2YV - 2 * dy * something / dist;
                                if (ballVY < -maxYV) {
                                    ballVY = -maxYV;
                                }
                                if (ballVY > maxYV) {
                                    ballVY = maxYV;
                                }
                            }
                            fP2Touched = true;
                        }
                        // hits left wall
                        if (ballX < 15) {
                            ballX = 15;
                            ballVX = -ballVX;
                        }
                        // hits right wall
                        if (ballX > 985) {
                            ballX = 985;
                            ballVX = -ballVX;
                        }
                        // hits the post
                        if (ballX > 480 && ballX < 520 && ballY < 140) {
                            // bounces off top of net
                            if (ballVY < 0 && ballY > 130) {
                                ballVY *= -1;
                                ballY = 130;
                            } else if (ballX < 500) { // hits side of net
                                ballX = 480;
                                ballVX = ballVX >= 0 ? -ballVX : ballVX;
                            } else {
                                ballX = 520;
                                ballVX = ballVX <= 0 ? -ballVX : ballVX;
                            }
                        }
                    }
            
                    // clear the ball position
                    int ballXPix = ballOldX * nWidth / 1000;
                    int ballYPix = 4 * nHeight / 5 - ballOldY * nHeight / 1000;
                    int ballRadPix = (ballRad + fudge) * nHeight / 1000;
                    // clear the old ball position
                    screen.setColor(Color.blue);
                    screen.fillRect(ballXPix - ballRadPix, ballYPix - ballRadPix, 2 * ballRadPix, 2 * ballRadPix);
                }
            And this is urgent, so I appreciate any help possible.
            Edited by: Slimer3 on Jan 21, 2010 4:13 PM

            Edited by: Slimer3 on Jan 21, 2010 5:41 PM
            • 3. Re: Slime Volleyball physics ball movement
              843853
              Slimer3 wrote:
              /* i have nfi what this is. i'm supposed to have done engineering
              dynamics and i can't remember any equation with x*x'+y*y' in it...
              it was a long time ago! - wedgey */
              It was even longer ago: think Pythagoras ;-)
              • 4. Re: Slime Volleyball physics ball movement
                843853
                thanks a lot! that hint really helped. now i kind of understand how wedgey got the collision detection to work. however, i still have a problem. the ball appears to be floating, though its is because of
                if (dy > 0 && dist < SLIMER_DIAM + BALL_RADIUS && dist > fudge) 
                but if i change it to
                if (dy > 0 && dist < SLIMER_RADIUS + BALL_RADIUS && dist > fudge) 
                it touches the slimer but the triangle border around around the slimer becomes smaller and causes the ball to be able to intersect with the slimer - which is what i don't want.
                so any hints as to what i could do to make the collision detection more realistic like wedgey's slime volleyball?
                btw, my code is:
                private void moveBall() {       // need to get it to look like an actual slime game
                        int fudge = 2; // was 5. a fudge factor.
                        int maxXV = 10; // was 15
                        int maxYV = 10; // was 22
                
                        // move the ball
                        ballPt.y += --vBallY;
                        ballPt.x += vBallX;
                
                        // collision detection
                        int dx = 2 * (ballPt.x - slimerPt1.x);
                        int dy = ballPt.y - slimerPt1.y;
                        int dist = (int) Math.sqrt(dx * dx + dy * dy);
                        int dvx = vBallX - vP1X;
                        int dvy = vBallY - vP1Y;
                        if (dy > 0 && dist < SLIMER_DIAM + BALL_RADIUS && dist > fudge) {
                            int something = (dx * dvx + dy * dvy) / dist;
                            ballPt.x = slimerPt1.x + (SLIMER_DIAM + BALL_RADIUS) / 2 * dx / dist;
                            ballPt.y = slimerPt1.y + (SLIMER_DIAM + BALL_RADIUS) * dy / dist;
                            // cap the velocity
                            if (something <= 0) {
                                vBallX += vP1X - 2 * dx * something / dist;
                                if (vBallX < -maxXV) {
                                    vBallX = -maxXV;
                                }
                                if (vBallX > maxXV) {
                                    vBallX = maxXV;
                                }
                                vBallY += vP1Y - 2 * dy * something / dist; //go back up
                                if (vBallY < -maxYV) {
                                    vBallY = -maxYV;
                                }
                                if (vBallY > maxYV) {
                                    vBallY = maxYV;
                                }
                            }
                        }
                
                        // that stuff all over again, but for p2.
                        dx = 2 * (ballPt.x - slimerPt2.x);
                        dy = ballPt.y - slimerPt2.y;
                        dist = (int) Math.sqrt(dx * dx + dy * dy);
                        dvx = vBallX - vP2X;
                        dvy = vBallY - vP2Y;
                        if (dy > 0 && dist < SLIMER_DIAM + BALL_RADIUS && dist > fudge) {
                            int something = (dx * dvx + dy * dvy) / dist;
                            ballPt.x = slimerPt2.x + (SLIMER_DIAM + BALL_RADIUS) / 2 * dx / dist;
                            ballPt.y = slimerPt2.y + (SLIMER_DIAM + BALL_RADIUS) * dy / dist;
                            if (something <= 0) {
                                vBallX += vP2X - 2 * dx * something / dist;
                                if (vBallX < -maxXV) {
                                    vBallX = -maxXV;
                                }
                                if (vBallX > maxXV) {
                                    vBallX = maxXV;
                                }
                                vBallY += slimerPt2.y - 2 * dy * something / dist;
                                if (vBallY < -maxYV) {
                                    vBallY = -maxYV;
                                }
                                if (vBallY > maxYV) {
                                    vBallY = maxYV;
                                }
                            }
                        }
                
                        // hits left wall
                        if (ballPt.x < 10) {
                            ballPt.x = 10;
                            vBallX = -vBallX;
                        }
                        // hits right wall
                        if (ballPt.x > 340) {
                            ballPt.x = 340;
                            vBallX = -vBallX;
                        }
                        // hits bottom floor
                        if (ballPt.y < 10) {
                            ballPt.y = 10;
                            vBallY = -vBallY;
                        }
                
                        //hits the net
                        if (ballPt.x > (screenRect.width - netWidth) / 2 - BALL_RADIUS && ballPt.x < (screenRect.width + netWidth) / 2 + BALL_RADIUS && ballPt.y < netHeight + BALL_RADIUS) {
                            // left side of net
                            if (ballPt.x < (screenRect.width - netWidth) / 2) {
                                ballPt.x = (screenRect.width - netWidth) / 2 - BALL_RADIUS;
                                vBallX = -vBallX;
                            } else if (ballPt.x > (screenRect.width + netWidth) / 2) {
                                ballPt.x = (screenRect.width + netWidth) / 2 + BALL_RADIUS;
                                vBallX = -vBallX;
                            } else {
                                vBallY = -vBallY;
                                ballPt.y = netHeight + BALL_RADIUS;
                            }
                        }
                    }
                thanks. btw, the slimers and ball are really all circles. i am also using the Point class and (0,0) are the coordinates for the centre of the slimer and ball. as well, the screen is rotated, so the origin is at the bottom left, not top left as it should be by default.

                Edited by: Slimer3 on Jan 22, 2010 2:36 PM

                Edited by: Slimer3 on Jan 22, 2010 2:39 PM
                • 5. Re: Slime Volleyball physics ball movement
                  843853
                  You need to check for collision before you do the update on the display and if you have a collision, then redraw the colliding ball in the proper orientation for your project--you make it contact the paddle at the appropriate place and not like it's sinking into the paddle.
                  • 6. Re: Slime Volleyball physics ball movement
                    843853
                    Initially, I tried finding the appropiate location to repaint the ball, but i was unsuccessful in getting the ball to move natually (ie. it moved in straight lines, not trajectory). as a result, i decided to use wedgeys collision code instead. this project is due on tuesday for me, so i wont have the time to change the current code because i also have an exam on monday. if at all possible, do you know how i could change the current collision code so that everything looks good and the ball collides visually with the slimer. currently, the slimer is surrounded by a triangle for collision purposes just like in wedgeys code, but i dont know how he got the ball and slimer to collide perfectly. i have changed the code so that collision detection is checked first, followed by drawing of slimers and ball.

                    thanks.
                    • 7. Re: Slime Volleyball physics ball movement
                      843853
                      Slimer3 wrote:
                      Initially, I tried finding the appropiate location to repaint the ball, but i was unsuccessful in getting the ball to move natually (ie. it moved in straight lines, not trajectory). as a result, i decided to use wedgeys collision code instead. this project is due on tuesday for me, so i wont have the time to change the current code because i also have an exam on monday.
                      Well, there seems to be your problem then, you just don't have enough time in your schedule to do it.
                      if at all possible, do you know how i could change the current collision code so that everything looks good and the ball collides visually with the slimer. currently, the slimer is surrounded by a triangle for collision purposes just like in wedgeys code, but i dont know how he got the ball and slimer to collide perfectly. i have changed the code so that collision detection is checked first, followed by drawing of slimers and ball.
                      Why did you choose this code to use for your project? It's beyond your abilities to understand.

                      Any way without running code, about all I can tell you is that you need to change the axis your ball is moving so ti hits your paddle and not goes into it. You can achieve this by remembering that the ball is a rectangle with origin measured at upper left corner so on the right side/ and bottom you have to subtract the paddle width from the position to make it collide naturally. On the top and left side, you do not, since the location of the ball is calculated from the upper left corner.
                      • 8. Re: Slime Volleyball physics ball movement
                        843853
                        originally, i got this code from oneslime.net. at first, i did create my own code, but it couldn't get the ball to move in a trajectory. so i had to resort to wedgeys code. i entirely agree with you that this code is beyond my understanding, but its too late for me to change my project.
                        You can achieve this by remembering that the ball is a rectangle with origin measured at upper left corner so on the right side/ and bottom you have to subtract the paddle width from the position to make it collide naturally. On the top and left side, you do not, since the location of the ball is calculated from the upper left corner.
                        - my origin is actually the bottom left. i used the translate method and scale method from Graphics2D to change it.

                        if it could help you help me, i can give you my current code (my so far completed program):
                        package SlimeGames;
                        
                        import java.awt.*;
                        import java.awt.event.*;
                        import javax.swing.JApplet;
                        
                        public class SlimeVolleyballPhysics extends JApplet
                                implements Runnable, KeyListener, MouseListener {
                        
                            boolean keyPressed[] = new boolean[4];
                            boolean gameStarted = false;
                            // game board and net
                            Rectangle screenRect, netRect;
                            // slimers
                            final int SLIMER_RADIUS = 25;
                            final int SLIMER_DIAM = 50;
                            Point slimerPt1, slimerPt2;
                            // ball
                            final int BALL_RADIUS = 10;
                            final int BALL_DIAM = 20;
                            Point ballPt; //this is used for movement co-ordinates of ball
                            int vP1X = 0, vP1Y = 0, vP2X = 0, vP2Y = 0; //velocity variables of slimers
                            boolean jump1 = false, jump2 = false;    //jumping
                            boolean ballUp = false; //ball bouncing direction
                            final int SLIMER_VELOCITY = 6;    //set velocity for horizontal and vertical
                            //movement of slimers
                            //for ball
                            //int ballPt.x = 0, ballPt.y = 0; //this is used for movement co-ordinates of ball
                            int vBallX = 0, vBallY = 0;   //velocity variables of ball
                            boolean fEndGame = false;
                            boolean fP1Touched = false, fP2Touched = false;
                            // The object we will use to write with instead of the standard screen
                            //graphics (double-buffering)
                            Graphics2D bufferGraphics;
                            // The image that will contain everything that has been drawn on
                            // bufferGraphics.
                            Image offscreen;
                            // To get the width and height of the applet.
                            Dimension dim;
                            // Variables for thread times
                            Thread gameThread;
                            long gameTime;
                            long currentTime;
                            long startTime;
                            // This variable will remain true for as long
                            // we want the thread to run.
                            boolean running = true;
                            int FRAME_RATE = 30;
                            int netWidth = 6;
                            int netHeight = 40;
                        
                            /** Initializes the applet NewJApplet */
                            @Override
                            public void init() {
                                // get the width and height of the entire image
                                dim = getSize();
                                addKeyListener(this);
                                addMouseListener(this);
                                setBackground(Color.blue);
                                // Create an offscreen image to draw on
                                // Make it the size of the applet, this is just perfect larger
                                // size could slow it down unnecessary.
                                offscreen = createImage(dim.width, dim.height);
                                // ballPt.y doing this everything that is drawn ballPt.y bufferGraphics
                                // will be written on the offscreen image.
                                bufferGraphics = (Graphics2D) offscreen.getGraphics();
                                // get screen size
                                screenRect = new Rectangle(0, 0, getSize().width, getSize().height);
                                // netRect = new Rectangle((screenRect.width - netWidth) / 2, screenRect.height - netHeight, netWidth, netHeight);
                        
                                // get the 2 slimey positions
                                slimerPt1 = new Point((screenRect.width / 2 - netWidth) / 2, 0);
                                slimerPt2 = new Point(screenRect.width - slimerPt1.x, 0);
                        
                                // ball init
                                ballPt = new Point(slimerPt1.x, screenRect.height / 2);
                        
                                vBallX = vBallY = 0;
                                // start double-buffering and threads
                                bufferGraphics = (Graphics2D) offscreen.getGraphics();
                                bufferGraphics.translate(0, getHeight());
                                bufferGraphics.scale(1.0, -1.0);
                            }
                        
                            //For initialization process only. Only activated once at the beginning.
                            //NOTE: this method is used if mouse input is to be included.
                            @Override
                            public void paint(Graphics g) {
                                g.setColor(Color.blue);
                                g.fillRect(0, 0, getWidth(), getHeight()); //The background
                            }
                        
                            public void moveSlimers() {
                                --vP1Y;
                                --vP2Y;
                                //slimer 1
                                slimerPt1.translate(vP1X, vP1Y);
                                if (slimerPt1.x < SLIMER_RADIUS) {
                                    slimerPt1.x = SLIMER_RADIUS;
                                }
                                if (slimerPt1.x > (screenRect.width - netWidth) / 2 - SLIMER_RADIUS) {
                                    slimerPt1.x = (screenRect.width - netWidth) / 2 - SLIMER_RADIUS;
                                }
                        
                                if (slimerPt1.y < 0) {
                                    slimerPt1.y = 0;
                                    vP1Y = 0;
                                    jump1 = false;
                                }
                        
                                //slimer 2
                                slimerPt2.translate(vP2X, vP2Y);
                                if (slimerPt2.x < (screenRect.width + netWidth) / 2 + SLIMER_RADIUS) {
                                    slimerPt2.x = (screenRect.width + netWidth) / 2 + SLIMER_RADIUS;
                                }
                        
                                if (slimerPt2.x > screenRect.width - SLIMER_RADIUS) {
                                    slimerPt2.x = screenRect.width - SLIMER_RADIUS;
                                }
                        
                                if (slimerPt2.y < 0) {
                                    slimerPt2.y = 0;
                                    vP2Y = 0;
                                    jump2 = false;
                                }
                            }
                        continued...
                        • 9. Re: Slime Volleyball physics ball movement
                          843853
                          private void moveBall() {
                                  int fudge = 2; // was 5. a fudge factor.
                                  int maxXV = 10; // was 15
                                  int maxYV = 10; // was 22
                          
                                  // move the ball
                                  ballPt.y += --vBallY;
                                  ballPt.x += vBallX;
                          
                                  // collision detection
                                  int dx = 2 * (ballPt.x - slimerPt1.x);
                                  int dy = ballPt.y - slimerPt1.y;
                                  int dist = (int) Math.sqrt(dx * dx + dy * dy);
                                  int dvx = vBallX - vP1X;
                                  int dvy = vBallY - vP1Y;
                                  if (dy > 0 && dist < SLIMER_DIAM + BALL_RADIUS && dist > fudge) {
                                      int something = (dx * dvx + dy * dvy) / dist;
                                      ballPt.x = slimerPt1.x + (SLIMER_DIAM + BALL_RADIUS) / 2 * dx / dist;
                                      ballPt.y = slimerPt1.y + (SLIMER_DIAM + BALL_RADIUS) * dy / dist;
                                      // cap the velocity
                                      if (something <= 0) {
                                          vBallX += vP1X - 2 * dx * something / dist;
                                          if (vBallX < -maxXV) {
                                              vBallX = -maxXV;
                                          }
                                          if (vBallX > maxXV) {
                                              vBallX = maxXV;
                                          }
                                          vBallY += vP1Y - 2 * dy * something / dist; //go back up
                                          if (vBallY < -maxYV) {
                                              vBallY = -maxYV;
                                          }
                                          if (vBallY > maxYV) {
                                              vBallY = maxYV;
                                          }
                                      }
                                  }
                          
                                  // that stuff all over again, but for p2.
                                  dx = 2 * (ballPt.x - slimerPt2.x);
                                  dy = ballPt.y - slimerPt2.y;
                                  dist = (int) Math.sqrt(dx * dx + dy * dy);
                                  dvx = vBallX - vP2X;
                                  dvy = vBallY - vP2Y;
                                  if (dy > 0 && dist < SLIMER_DIAM + BALL_RADIUS && dist > fudge) {
                                      int something = (dx * dvx + dy * dvy) / dist;
                                      ballPt.x = slimerPt2.x + (SLIMER_DIAM + BALL_RADIUS) / 2 * dx / dist;
                                      ballPt.y = slimerPt2.y + (SLIMER_DIAM + BALL_RADIUS) * dy / dist;
                                      if (something <= 0) {
                                          vBallX += vP2X - 2 * dx * something / dist;
                                          if (vBallX < -maxXV) {
                                              vBallX = -maxXV;
                                          }
                                          if (vBallX > maxXV) {
                                              vBallX = maxXV;
                                          }
                                          vBallY += slimerPt2.y - 2 * dy * something / dist;
                                          if (vBallY < -maxYV) {
                                              vBallY = -maxYV;
                                          }
                                          if (vBallY > maxYV) {
                                              vBallY = maxYV;
                                          }
                                      }
                                  }
                          
                                  // hits left wall
                                  if (ballPt.x < 10) {
                                      ballPt.x = 10;
                                      vBallX = -vBallX;
                                  }
                                  // hits right wall
                                  if (ballPt.x > 340) {
                                      ballPt.x = 340;
                                      vBallX = -vBallX;
                                  }
                                  // hits bottom floor
                                  if (ballPt.y < 10) {
                                      ballPt.y = 10;
                                      vBallY = -vBallY;
                                  }
                          
                                  //hits the net
                                  if (ballPt.x > (screenRect.width - netWidth) / 2 - BALL_RADIUS && ballPt.x < (screenRect.width + netWidth) / 2 + BALL_RADIUS && ballPt.y < netHeight + BALL_RADIUS) {
                                      // left side of net
                                      if (ballPt.x < (screenRect.width - netWidth) / 2) {
                                          ballPt.x = (screenRect.width - netWidth) / 2 - BALL_RADIUS;
                                          vBallX = -vBallX;
                                      } else if (ballPt.x > (screenRect.width + netWidth) / 2) {
                                          ballPt.x = (screenRect.width + netWidth) / 2 + BALL_RADIUS;
                                          vBallX = -vBallX;
                                      } else {
                                          vBallY = -vBallY;
                                          ballPt.y = netHeight + BALL_RADIUS;
                                      }
                                  }
                              }
                          
                              @Override
                              public void run() {
                                  startTime = System.currentTimeMillis();
                                  // loop until told to stop
                                  while (running) {
                                      drawSlimers();
                                      drawBall();
                                      moveBall();
                                      drawStatus();
                                      Graphics g = getGraphics();
                                      try {
                                          // Wait 33 milliseconds before continuing
                                          Thread.sleep(1000 / FRAME_RATE);
                                      } catch (InterruptedException e) {
                                          System.out.println(e);
                                      }
                                      g.drawImage(offscreen, 0, 0, this);
                                      g.setColor(Color.white);
                                      g.drawString(makeTime(gameTime), screenRect.width / 3, screenRect.height / 3);
                                  }
                              }
                          
                              private void drawSlimers() {
                                  bufferGraphics.clearRect(0, 0, dim.width, dim.width);
                                  moveSlimers();
                                  bufferGraphics.setColor(Color.blue);
                                  bufferGraphics.fillRect(0, 0, screenRect.width, screenRect.height); //The background
                                  bufferGraphics.setColor(Color.red);
                                  bufferGraphics.fillArc(slimerPt1.x - SLIMER_RADIUS, slimerPt1.y - SLIMER_RADIUS, 2 * SLIMER_RADIUS, 2 * SLIMER_RADIUS, 0, -180); //P1 Slimeys
                                  bufferGraphics.setColor(Color.pink);
                                  bufferGraphics.fillArc(slimerPt2.x - SLIMER_RADIUS, slimerPt2.y - SLIMER_RADIUS, 2 * SLIMER_RADIUS, 2 * SLIMER_RADIUS, 0, -180); //P2 Slimeys
                                  bufferGraphics.setColor(Color.white);
                                  bufferGraphics.fillOval(slimerPt1.x - SLIMER_RADIUS + 30, SLIMER_RADIUS - 10 + slimerPt1.y, 10, 10); //P1 Eyes
                                  //30+10 = 40 (10 from the right) which matches the distance for the
                                  //second slime too: 10 from the left
                                  bufferGraphics.fillOval(slimerPt2.x - SLIMER_RADIUS + 10, SLIMER_RADIUS - 10 + slimerPt2.y, 10, 10); //P2 Eyes
                                  // -25 because the fill works from the top left corner towards the
                                  //bottom right corner
                                  bufferGraphics.fillRect(screenRect.width / 2 - netWidth / 2, 0, netWidth, netHeight); //The net: 3 units on both
                                  //sides form a total of 6 units wide
                                  bufferGraphics.setColor(Color.black);
                                  bufferGraphics.fillOval(slimerPt1.x - SLIMER_RADIUS + 35, SLIMER_RADIUS - 6 + slimerPt1.y, 5, 5); //P1 Eyeballs
                                  bufferGraphics.fillOval(slimerPt2.x - SLIMER_RADIUS + 10, SLIMER_RADIUS - 6 + slimerPt2.y, 5, 5); //P2 Eyeballs
                              }
                          
                              private void drawBall() {
                                  bufferGraphics.setColor(Color.yellow);
                                  bufferGraphics.fillOval(ballPt.x - BALL_RADIUS, ballPt.y - BALL_RADIUS, BALL_RADIUS * 2, BALL_RADIUS * 2);
                              //bufferGraphics.fillOval(ballPt.x , ballPt.y , BALL_RADIUS , BALL_RADIUS );
                              //ballPt.x + rightBorder / 4 - BALL_RADIUS, ballPt.y + topBorder + BALL_RADIUS
                              // Volleyball
                              }
                          
                              private void drawStatus() {
                                  currentTime = System.currentTimeMillis();
                                  gameTime = currentTime - startTime;
                          //        Graphics g = getGraphics();
                                  bufferGraphics.setColor(Color.white);
                          //        bufferGraphics.drawString(makeTime(gameTime), screenRect.width / 3,
                          //                2 * screenRect.height / 3);
                              }
                          • 10. Re: Slime Volleyball physics ball movement
                            843853
                            private String makeTime(long l) {  //Taken from Wedgey's code
                                    long l1 = (l / 10L) % 100L;
                                    long l2 = (l / 1000L) % 60L;
                                    long l3 = (l / 60000L) % 60L;
                                    long l4 = l / 0x36ee80L;
                                    String s = "";
                                    if (l4 < 10L) {
                                        s += "0";
                                    }
                                    s += l4;
                                    s += ":";
                                    if (l3 < 10L) {
                                        s += "0";
                                    }
                                    s += l3;
                                    s += ":";
                                    if (l2 < 10L) {
                                        s += "0";
                                    }
                                    s += l2;
                                    s += ":";
                                    if (l1 < 10L) {
                                        s += "0";
                                    }
                                    s += l1;
                                    return s;
                                }
                            
                                public void checkKeyPressed() {
                                    if (keyPressed[0] == true) {
                                        vP1X = -SLIMER_VELOCITY;
                                    }
                                    if (keyPressed[1] == true) {
                                        vP1X = SLIMER_VELOCITY;
                                    }
                                    if (keyPressed[2] == true) {
                                        vP2X = -SLIMER_VELOCITY;
                                    }
                                    if (keyPressed[3] == true) {
                                        vP2X = SLIMER_VELOCITY;
                                    }
                                }
                            
                                public void keyTyped(KeyEvent e) {
                                }
                            
                                public void keyPressed(KeyEvent e) {
                                    int key1 = e.getKeyCode();
                                    if (key1 == KeyEvent.VK_A) {
                                        keyPressed[0] = true;
                                    }
                                    if (key1 == KeyEvent.VK_D) {
                                        keyPressed[1] = true;
                                    }
                                    if (jump1 == false) {
                                        if (key1 == KeyEvent.VK_W) {
                                            jump1 = true;
                                            //gravity effect added here
                                            vP1Y = 11;
                                        }
                                    }
                            
                                    if (key1 == KeyEvent.VK_LEFT) {
                                        keyPressed[2] = true;
                                    }
                                    if (key1 == KeyEvent.VK_RIGHT) {
                                        keyPressed[3] = true;
                            
                                    }
                                    if (jump2 == false) {
                                        if (key1 == KeyEvent.VK_UP) {
                                            jump2 = true;
                                            //gravity effect added here
                                            vP2Y = 11;
                                        }
                                    }
                                    checkKeyPressed();
                                }
                            
                                public void keyReleased(KeyEvent e) {
                                    int key1 = e.getKeyCode();
                                    if (key1 == KeyEvent.VK_A) {
                                        keyPressed[0] = false;
                                        vP1X = 0;
                                    }
                                    if (key1 == KeyEvent.VK_D) {
                                        keyPressed[1] = false;
                                        vP1X = 0;
                                    }
                            
                                    if (key1 == KeyEvent.VK_LEFT) {
                                        keyPressed[2] = false;
                                        vP2X = 0;
                                    }
                                    if (key1 == KeyEvent.VK_RIGHT) {
                                        keyPressed[3] = false;
                                        vP2X = 0;
                                    }
                                    checkKeyPressed();
                                }
                            
                                @Override
                                public void destroy() {
                                    // will cause thread to stop looping
                                    running = false;
                                    // destroy the thread
                                    gameThread = null;
                                }
                            
                                public void mouseClicked(MouseEvent e) {
                                    if (gameStarted == false) {
                                        gameStarted = true;
                                        gameThread = new Thread(this);
                                        gameThread.start();
                                    }
                                }
                            
                                public void mousePressed(MouseEvent e) {
                                }
                            
                                public void mouseReleased(MouseEvent e) {
                                }
                            
                                public void mouseEntered(MouseEvent e) {
                                }
                            
                                public void mouseExited(MouseEvent e) {
                                }
                            }
                            • 11. Re: Slime Volleyball physics ball movement
                              843853
                              as you can see, my only problem left is basically the collision/physics part. any advice is highly appreciated.

                              thanks.