Wall rebound sometimes fails

Hi,

I am pretty new in programming and got the task to create a kind of a billard game. Now I have the problem that sometimes the ball did not rebound from the wall.

I hope you can help me out. Thanks for that.

Below you can find my current code.

Tagged:

Answers

  •    float xPosition;                                                                      //X-Koordinate
        float yPosition;                                                                      //Y-Koordinate
        float xDirection;                                                                     //X-Richtung
        float yDirection;                                                                     //Y-Richtung
        float xSpeed;                                                                         //X-Geschwindigkeit
        float ySpeed;                                                                         //Y-Geschwindigkeit
        int diameter;                                                                         //Kreisdurchmesser
        float friction;                                                                       //Reibung
        float absorption;                                                                     //Dämpfung                                                           
        float currentMouseX;                                                                  //aktuelle X-Mausposition
        float currentMouseY;                                                                  //aktuelle Y-Mausposition
        float previousMouseX;                                                                 //vorherige X-Mausposition
        float previousMouseY;                                                                 //vorherige Y-Mausposition
    
        void setup() {                                                                        //Initialisierungen
          size(600, 400);                                                                     //Fenstergröße 600x400 Pixel
          background(#147615);                                                                //dunkelgrüner Hintergrund
          xPosition = width/2;                                                                //X-Startpunkt: 300 Pixel
          yPosition = height/2;                                                               //Y-Startpunkt: 200 Pixel
          diameter = 50;                                                                      //Kreisdurchmesser: 50 Pixel
          xDirection = 1;                                                                     //X-Richtung: 1 Pixel
          yDirection = 1;                                                                     //Y-Richtung: 1 Pixel
          xSpeed = 3;                                                                         //X-Geschwindigkeit: 10 Pixel
          ySpeed = 3;                                                                         //Y-Geschwindigkeit: 10 Pixel
          friction = 0.995;                                                                   //Reibung: 0,5%
          absorption = 0.75;                                                                  //Dämpfung: 25%
          previousMouseX = 0;                                                                 //aktuelle X-Mausposition
          currentMouseX = 0;                                                                  //aktuelle Y-Mausposition
          previousMouseY = 0;                                                                 //vorherige X-Mausposition
          currentMouseY = 0;                                                                  //vorherige Y-Mausposition
        }
    
        void draw() {
          background(#147615);                                                                //dunkelgrüner Hintergrund
          checkDirection();                                                                   //aktuelle Richtung prüfen
          checkSpeed();                                                                       //aktuelle Geschwindigkeit prüfen
          checkBoundaries();                                                                  //aktuelle Position prüfen
          noStroke();                                                                         //kein Rahmen
          ellipse(xPosition, yPosition, diameter, diameter);                                  //Kreis
        }
    
    
        void checkBoundaries() {
          if (xPosition < diameter/2) {                                                       //linker Rand erreicht?
            xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
            xDirection = -xDirection;                                                         //X-Richtung invertieren
          } 
          if (xPosition > width-diameter/2) {                                                 //rechter Rand erreicht?
            xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
            xDirection = -xDirection;                                                         //X-Richtung invertieren
          }  
          if (yPosition < diameter/2) {                                                       //oberer Rand erreicht?
            ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
            yDirection = -yDirection;                                                         //Y-Richtung invertieren
          }
          if (yPosition > height-diameter/2) {                                                //unterer Rand erreicht?
            ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
            yDirection = -yDirection;                                                         //Y-Richtung invertieren
          }
        }
    
        void checkSpeed() {
          if ((xSpeed >= 0.05 ) || (ySpeed >= 0.05) || (xSpeed == 0 && ySpeed == 0)) {        //Kreis bewegt sich?
            xSpeed = xSpeed * friction;                                                       //Reibung abziehen
            ySpeed = ySpeed * friction;                                                       //Reibung abziehen
          } else {
            xSpeed = 0;                                                                       //Bewegung anhalten
            ySpeed = 0;                                                                       //Bewegung anhalten
            noStroke();                                                                       //kein Rahmen
            ellipse(xPosition, yPosition, diameter, diameter);                                //Kreis
            fill(0);                                                                          //schwarze Füllung
          }
        }
    
        void checkDirection() {
          if (mousePressed) {                                                                 //Maustaste gedrückt?
            setup();                                                                          //Initialisierungen aufrufen
            currentMouseX = mouseX;                                                           //aktuelle X-Mausposition
            currentMouseY = mouseY;                                                           //aktuelle Y-Mausposition
            previousMouseX = pmouseX;                                                         //vorherige X-Mausposition
            previousMouseY = pmouseY;                                                         //vorherige Y-Mausposition
            xPosition = mouseX;                                                               //aktuelle X-Mausposition
            yPosition = mouseY;                                                               //aktuelle Y-Mausposition
            xSpeed = abs(mouseX - pmouseX);                                                   //X-Mausbeschleunigung 
            ySpeed = abs(mouseY - pmouseY);                                                   //Y-Mausbeschleunigung
            noStroke();                                                                       //kein Rahmen
            ellipse(currentMouseX, currentMouseY, diameter, diameter);                        //Kreis
            fill(255);                                                                        //weiße Füllung
          }
    
    
          if (!mousePressed && currentMouseX != 0) {                                          //Maustaste nicht gedrückt?
            if (currentMouseX > previousMouseX && currentMouseY > previousMouseY) {           //X positiv? und Y positiv? 
              xPosition = xPosition + xSpeed * xDirection;                                    //positive X-Bewegung
              yPosition = yPosition + ySpeed * yDirection;                                    //prositive Y-Bewegung
            }
            if (currentMouseX > previousMouseX && currentMouseY < previousMouseY) {           //X positiv? und Y negativ?
              xPosition = xPosition + xSpeed * xDirection;                                    //positive X-Bewegung
              yPosition = yPosition - ySpeed * yDirection;                                    //negative Y-Bewegung
            }
            if (currentMouseX < previousMouseX && currentMouseY > previousMouseY) {           //X negativ? und Y positiv?
              xPosition = xPosition - xSpeed * xDirection;                                    //negative X-Bewegung
              yPosition = yPosition + ySpeed * yDirection;                                    //positive Y-Bewegung
            }
            if (currentMouseX < previousMouseX && currentMouseY < previousMouseY) {           //X negativ? und Y negativ?
              xPosition = xPosition - xSpeed * xDirection;                                    //negative X-Bewegung
              yPosition = yPosition - ySpeed * yDirection;                                    //negative Y-Bewegung
            }  
            if (currentMouseX < previousMouseX && currentMouseY == previousMouseY) {          //X negativ? und Y neutral?
              xPosition = xPosition - xSpeed * xDirection;                                    //negative X-Bewegung
            }
            if (currentMouseX > previousMouseX && currentMouseY == previousMouseY) {          //X positiv? und Y neutral?
              xPosition = xPosition + xSpeed * xDirection;                                    //positive X-Bewegung
            }
            if (currentMouseX == previousMouseX && currentMouseY > previousMouseY) {          //X neutral? und Y positiv?
              yPosition = yPosition + ySpeed * yDirection;                                    //positive Y-Bewegung
            }  
            if (currentMouseX == previousMouseX && currentMouseY < previousMouseY) {          //X neutral? und Y negativ?
              yPosition = yPosition - ySpeed * yDirection;                                    //negative Y-Bewegung
            }
          }
        }
    
  • in my opinion, this

    yDirection = -yDirection;

    can lead to stuttering near the screen border in that it can just go back and forth between a negative and a positive value.

    To avoid stuttering better say

    yDirection = - abs(yDirection); // always negative

    OR

    yDirection = abs(yDirection); // always positive

  • I have implemented your suggested improvement.

    The ball rebound seems to work except the ball hits the upper border first.

  • void checkBoundaries() {
      if (xPosition < diameter/2) {                                                       //linker Rand erreicht?
        xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
        xDirection = -abs(xDirection);                                                    //X-Richtung invertieren
      } 
      if (xPosition > width-diameter/2) {                                                 //rechter Rand erreicht?
        xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
        xDirection = abs(xDirection);                                                     //X-Richtung invertieren
      }  
      if (yPosition < diameter/2) {                                                       //oberer Rand erreicht?
        ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
        yDirection = abs(yDirection);                                                     //Y-Richtung invertieren
      }
      if (yPosition > height-diameter/2) {                                                //unterer Rand erreicht?
        ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
        yDirection = -abs(yDirection);                                                    //Y-Richtung invertieren
      }
    }
    
  • edited April 2017

    excuse me, is the -abs and the abs section the other way round in line 4 and 8 ?

    when it's xPosition < diameter/2 we want xDirection = abs(xDirection);

    when it's xPosition > width-diameter/2 we want xDirection = - abs(xDirection);

    here

    void checkBoundaries() {
      if (xPosition < diameter/2) {                                                       //linker Rand erreicht?
        xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
        xDirection = abs(xDirection);                                                    //X-Richtung invertieren
      } 
      if (xPosition > width-diameter/2) {                                                 //rechter Rand erreicht?
        xSpeed = xSpeed * absorption;                                                     //Dämpfung abziehen
        xDirection = -abs(xDirection);                                                     //X-Richtung invertieren
      }  
      if (yPosition < diameter/2) {                                                       //oberer Rand erreicht?
        ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
        yDirection = abs(yDirection);                                                     //Y-Richtung invertieren
      }
      if (yPosition > height-diameter/2) {                                                //unterer Rand erreicht?
        ySpeed = ySpeed * absorption;                                                     //Dämpfung abziehen
        yDirection = -abs(yDirection);                                                    //Y-Richtung invertieren
      }
    }
    
  • Tried to change the minus and plus, but did not solve the problem. :(( :(( :((

  • You need to study this example: https://processing.org/examples/bounce.html

    You have two variables per dimension: xDirection and xSpeed for example. However you do not need two variables. One is enough. The sign of the variable defines direction. The magnitude, or abs(value) defines the effective value in that dimension along a direction. If you split the magnitude from direction, you are creating more work for yourself. You don't have to. I believe thinks will be more clear if you check the example.

    Kf

  • Changed the collision detection according to the example and found out that everything seems to work fine, if I don't calculate the wall absorption.

  • It's not good to call setup really

    Instead make a new function init() and call this

    Basically move all from setup into init except for size

    I don't see why you store mouseX, mouseY and pmouseX and pmouseY! just work with original variables mouseX etc.

    You are throwing the ball with the mouse, right? I think that can be written easier when you say mouseX - pmouseX ---- but make a copy first.......

  • edited April 2017

    I store mouseX, mouseY and pmouseX and pmouseY, because if the mouse is released the two last position are saved in those variables. With the stored values I can find out the last direction the ball made. I know it could be written easier, but my tries with the original variables failed.

Sign In or Register to comment.