My Balls are getting stuck at the bottom of the application

edited March 2014 in Questions about Code

Hi all, I've made a simple application that just let my balls bounce. Normally my balls would bounce when they hit the black bar. But sometimes they get stuck in it. i've tried alot of things, and now i replace them in the middle of the screen when they reach a specific height.. Hopefully you can help me out!

Thankss

ballgoeswrong

class Ball
{
  //Global Variables
  float x = 0;
  float y = 0;
  int ballSize = 30;
  float speedX = random(1, 5);
  float speedY = random(0.5, 5);
  float r;
  float g;
  float b;
  int id;
 // PVector = position;


  //Constuctor
  Ball(float _x, float _y)
  {
    x = _x;
    y = _y;
    r = random(255);
    g = random(255);
    b = random(255);
  }

  //Functions
  void run()
  {
    display();
    move(); 
    bounce();
    gravity();
    //println(speedX);
  }

  void display()
  {
    ellipse(x, y, 20, 20);
    fill(r, g, b);
  }
  void move()
  {
    x += speedX;
    y += speedY;
  }

  void bounce()
  {
    if (x + 10 > width + 2)
    {
      speedX = speedX * -1;
    }
    if (x -10 < 0)
    {
      speedX = speedX * -1;
    }
    if (y + 20 > height - 10)
    {
      speedY = speedY * -1;
    }
    if (y - 13 < 0)
    {
      speedY = speedY * -1;
    }
    if (y >793)
    {
      x = width -10;
      y = height/2;
    }
    if (speedX > 5)
    {
      speedX = random(1, 5);
    }
    if (speedY > 30)
    {
      speedY = random(0.5, 5);
    }
  }
  void gravity()
  {
    speedY += 0.2;
  }
  void collision()
  {

  }

Answers

  • edited March 2014

    Tell me now what is the problem ,

    ArrayList<Ball> poop = new ArrayList();
    int barheight = 10;
    void setup() {
      size(400, 400);
      for (int i=0;i<10;i++) {
        Ball B = new Ball(random(width), random(width));
        poop.add(B);
      }
    }
    
    void draw() {
      background(-1);
      for (int i=0;i<poop.size();i++) {
        Ball B  = (Ball) poop.get(i);
        B.display();
        B.run();
        B.move();
        B.bounce();
      }
      fill(0);
      rect(0, height-barheight, width, barheight);
    }
    
    
    class Ball
    {
      //Global Variables
      float x = 0;
      float y = 0;
      float speedX = random(1, 5);
      float speedY = random(0.5, 5);
      float r;
      float g;
      float b;
      int id;
      int rad = 10;
      // PVector = position;
    
    
      //Constuctor
      Ball(float _x, float _y)
      {
        x = _x;
        y = _y;
        r = random(255);
        g = random(255);
        b = random(255);
      }
    
      //Functions
      void run()
      {
        display();
        move(); 
        bounce();
        gravity();
        //println(speedX);
      }
    
      void display()
      {
        fill(r, g, b);
        ellipse(x, y, 2*rad, 2*rad);
      }
      void move()
      {
        x += speedX;
        y += speedY;
      }
    
      void bounce()
      {
        if (x + rad > width)
        {
          speedX = speedX * -1;
        }
        if (x - rad < 0)
        {
          speedX = speedX * -1;
        }
        if (y + rad > height - barheight)
        {
          speedY = speedY * -1;
        }
        if (y - rad < 0)
        {
          speedY = speedY * -1;
        }
        if (y >height-barheight)
        {
          x = width - rad;
          y = height/2;
        }
        if (speedX > 5)
        {
          speedX = random(1, 5);
        }
        if (speedY > 30)
        {
          speedY = random(0.5, 5);
        }
      }
      void gravity()
      {
        speedY += 0.2;
      }
      void collision()
      {
      }
    }
    
  • they get stuck GoToLoop...

  • Again, you've been given an example that you seem to be ignoring. How can we help you if you ignore the advice you've been given?

    The problem is that you aren't setting the ball's position after it hits the black bar, so the ball is still colliding with it. So if the speedY isn't fast enough to go back outside of the black bar on the next step, you'll still be colliding and you'll bounce back down and back up infinitely.

  • edited March 2014

    Don't abuse of the Reject button, it is not mandatory. The advices of KevinWorkman are good, read them again. If you don't understand them, ask questions instead of rejecting the explanations.

  • edited March 2014

    I still don't like this:

     if (x + rad > width)
        {
          speedX = speedX * -1;
        }
        if (x - rad < 0)
        {
          speedX = speedX * -1;
        }
        if (y + rad > height - barheight)
        {
          speedY = speedY * -1;
        }
        if (y - rad < 0)
        {
          speedY = speedY * -1;
        }
    

    because when speedX is relatively small it could be that we stay outside the screen and then *-1 is used again which leads to stutter

    better

     if (x + rad > width)
        {
          speedX = abs(speedX) * -1; // always neg
        }
        if (x - rad < 0)
        {
          speedX = abs(speedX);  // always pos 
        }
        if (y + rad > height - barheight)
        {
          speedY = abs(speedY) * -1; // always neg
        }
        if (y - rad < 0)
        {
          speedY = abs(speedY);   // always pos
        }
    
  • Making an extra move() like I did w/ the online example is a valid fix too. :>

  • edited March 2014

    Like @KevinWorkman wrote, set velocity and position after any collision and nothing will get stuck:

    void bounce() {
        if(x + rad > width) {
            x = width - rad;
            speedX = -speedX;
        }
        if(x - rad < 0.0) {
            x = rad;
            speedX = -speedX;
        }
        if(y + rad > height - barHeight) {
            y = height - barHeight - rad;
            speedY = -speedY;
        }
        if(y - rad < 0.0) {
            y = rad;
            speedY = -speedY;
        }
        if(speedX > 5.0) {
            speedX = random(1.0, 5.0);
        }
        if(speedY > 30.0) {
            speedY = random(0.5, 5.0);
        }
    }
    

    The above code will work even if you forcefully (via player interaction/console inputs/scripts/etc.) move a ball out of the allowed bounding box (screen) - simple velocity mirroring would fail in this case.

    Also have a look at @GoToLoop's code, his extra move() basically does the same thing.

  • edited March 2014

    Personally I prefer @Chrisir's solution, though I would make a couple of changes

       if (x + rad > width)   {
         speedX = -abs(speedX); // always neg
       }
       else if (x - rad < 0)   {
         speedX = abs(speedX);  // always pos
       }
       if (y + rad > height - barheight)   {
         speedY = -abs(speedY); // always neg
       }
       else if (y - rad < 0)   {
         speedY = abs(speedY);   // always pos
       }
    

    I always use this approach because

    a) simply negating the velocity doesn't always work

    b) negating the velocity and moving the ball back inside the box could cause jerks in the bounce at high velocity

    c) done correctly it works in all cases.

Sign In or Register to comment.