0

My bouncing ball is meant to bounce between 200x200 window's borders. I'v managed to make him stop and change direction when he touches the right and bottom borders. But when he reaches the top and left borders, a 1/4 of the ball goes through the border and only then it changes direction.

I have no idea why it happens, I mean it's literally the same code lines for each border. How can it even be that for the same code it will work differently?

I went through lots of codes around the net about this topic, and tried every solution or code, and it's still stays the same.

Thanks.

 public Point applyToPoint(Point p) {
        return new Point(p.getX() + dx, p.getY() + dy);
    }

    public void moveOneStep(int width, int height) {
    if (this.center.getX() + this.getVelocity().dx + r > width) {
        this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
    }
    if (this.center.getX() + this.getVelocity().dx < 0) {
        this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
    }
    if (this.center.getY() + this.getVelocity().dy + r > height) {
        this.setVelocity(this.getVelocity().dx, -(this.getVelocity().dy));
    }
    if (this.center.getY() + this.getVelocity().dy < 0) {
        this.setVelocity(this.getVelocity().dx, -(this.getVelocity().dy));
    }
    moveOneStep();
}

public void moveOneStep() {
    this.center = this.getVelocity().applyToPoint(this.center);
}

r = radius of the ball.

"this.center" = the center point of the ball.

screenshot of the ball on the left border:

img

 import biuoop.DrawSurface;
import biuoop.GUI;
import biuoop.Sleeper;

public class BouncingBallAnimation {

    static private void drawAnimation(Point start, double dx, double dy) {
        GUI gui = new GUI("BouncingBall",200,200);
        Sleeper sleeper = new Sleeper();
        Ball ball = new Ball(new Point(start.getX(), start.getY()), 30, java.awt.Color.BLACK);
        ball.setVelocity(dx, dy);
        while (true) {
            DrawSurface d = gui.getDrawSurface();
            ball.moveOneStep(d.getHeight(),d.getWidth());
            ball.drawOn(d);
            gui.show(d);
            sleeper.sleepFor(50);  // wait for 50 milliseconds.
        }
    }
    public static void main(String[] args) {
        drawAnimation(new Point(20,33),6,6); //just a random input that I decided
    }
}
Spektre
  • 49,595
  • 11
  • 110
  • 380
Dima Ciun
  • 87
  • 1
  • 11

2 Answers2

0

I mean it's literally the same code lines for each border

And that would be the problem. How can it be the same because you have different situations?

When the ball moves to the right/down the x/y values increase.

When the ball move to the left/up the x/y values decrease.

if (this.center.getX() + this.getVelocity().dx < 0) {

I would guess that should be:

if (this.center.getX() - this.getVelocity().dx - r < 0) {

This assumes that the "center" is actually the center of the circle.

Edit:

Also:

    this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getX() + this.getVelocity().dx < 0) {
    this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);

How can the x velocity change be negative in both cases.

When moving to the right you go from a positive velocity to a negative velocity

So when going to the left should you not be going from a negative velocity to a positive velocity?

camickr
  • 321,443
  • 19
  • 166
  • 288
  • yes I thought about it, I thought your solution and also about subtracting the "r". nothing worked. Your solution just gets the ball stuck in the starting point and he won't move from there. Doesn't it suppose to be the opposite? I mean y values should increase when the ball moves up, at least I think so. – Dima Ciun Apr 23 '20 at 03:10
  • Yes, you are correct. you should also subtract the "r". So did you actually display the value that is calculated? – camickr Apr 23 '20 at 03:13
  • *I mean y values should increase when the ball moves up, at least I think so.* - no. The top/left is (0, 0) and the bottom/right is (200, 200). Again. what debugging have you done to display the value that are calculated? – camickr Apr 23 '20 at 03:15
  • I tried subtracting the radius and basically tried every possible option for at least 3 times. I don't know why I can't find the solution here. And no, I don't display the value that is calculated. – Dima Ciun Apr 23 '20 at 03:17
  • Then how do you know if the calculation is correct? How do you know that the 'center" is actually the center of the circle? Don't assume anything. Display the 3 values used in the calculation so see if they make sense. Don't just guess that your formula is correct. – camickr Apr 23 '20 at 03:18
  • because i'm using the following package which gives me the option to draw a circle and just fill in coordinates for the center point. http://planet.cs.biu.ac.il/~kleinay/biuoop-1.4-doc/ , Please have a look at DrawSurface about drawCircle – Dima Ciun Apr 23 '20 at 03:22
  • The package is irrelevant. What is relevant is the value of the 3 variables used in the calculation. If you don't know what the 3 value are how will you ever know when their total is less than 0? This is basic debugging and problem solving! – camickr Apr 23 '20 at 03:24
  • Oh sorry I didn't understand you. Of course I debugged this, multiple times. I enter the values of: drawAnimation(new Point(1,3),6,6); – Dima Ciun Apr 23 '20 at 03:30
  • 1) I have absolutely no idea what drawAnimation(...() is. It has nothing to do with the code you posted here. 2) I said there are 3 value used in the calculation, You need to know what all 3 value are and the total should increase/decrease sequentially based on your velocity. 3) see edit for another possible problem. – camickr Apr 23 '20 at 03:32
  • I did try to make it a positive velocity when the ball moves left, because as you said: When I touch the right border, I change to a negative velocity and then when i'll touch the left border I want to change to a positive one again. The problem is that when I do that, the ball just continues through the left border and never stops – Dima Ciun Apr 23 '20 at 03:41
  • I have added the drawAnimation to the main post. – Dima Ciun Apr 23 '20 at 03:46
  • My point is the code moving right works. So the code move left should be the "opposite" of the code moving right. Once again the drawAnimation() method is irrelevant. The problem with your code is with the "if condition" and/or the way you set the velocity when the "if condition" is true. I can't explain the concept any clearer than that. Since you don't understand the concept of display the value of the variables used in your "if condition" to verify if they are correct, I can't help. Good luck.. – camickr Apr 23 '20 at 03:48
  • See: https://stackoverflow.com/questions/54028090/get-width-and-height-of-jpanel-outside-of-the-class/54028681#54028681 for a working example. As you can see in the `move(…)` logic the x/y positions are set to 0, whenever the ball reaches the border. I'm guessing in your logic you temporarily allow the value to go negative until the next time the ball is moved. – camickr Apr 23 '20 at 04:04
0

Ok so here's the working code: public void moveOneStep(int startX, int height, int startY, int width) {

    if (this.center.getX() + this.getVelocity().dx + r >= width) {
        this.setVelocity(-1 * (this.getVelocity().dx), this.getVelocity().dy);
    }
    if (this.center.getX() + this.getVelocity().dx - r <= startX) {
        this.setVelocity(-1 * (this.getVelocity().dx), this.getVelocity().dy);
    }
    if (this.center.getY() + this.getVelocity().dy + r >= height) {
        this.setVelocity(this.getVelocity().dx, -1 * (this.getVelocity().dy));
    }
    if (this.center.getY() + this.getVelocity().dy - r <= startY) {
        this.setVelocity(this.getVelocity().dx, -1 * (this.getVelocity().dy));
    }
    moveOneStep();
}

The problem was not the code but the starting point I entered to check the circle. You can't give the circle a starting center point of lets say (20,50) if the Radius is 30. Why? Because then the circle will be out of bounds right from the beginning, because he has a starting center point of 20,50, and radius of 30, which means his left radius will reach (-10, 50). And that's why I had many problems. You always should check if the starting point fits the radius.

Dima Ciun
  • 87
  • 1
  • 11
  • Which is why you do basic debugging and display the values of your variables. Like I suggested if you display the values of the center.getX() and getVelocity().dx and r, then you would see that the relationship was wrong. Don't know why I had to repeat myself multiple times to get you to look at those values. – camickr Apr 24 '20 at 01:37