1

I need to change Ball Direction after collision with another ball or with a edge of the window. I managed to do something like that:

y += yMove;
x += xMove;

//if the ball moves to the right edge of the window, turn around. 
if(x > width - size)
{   
    x = width - size;
    xMove *= -1;
    if (xMove > 0) {
       xSpeed = xMove + (Math.random() * (1));
    }
    if (xMove <= 0) {
       xSpeed = xMove - (Math.random() * (1));
    }
    if (yMove > 0) {
       ySpeed = yMove + (Math.random() * (1));
    }
    if (yMove <= 0) {
       ySpeed = yMove - (Math.random() * (1));
    }
}

And same for another edges.

I'm trying to use same method for changing direction of balls after they collide with each other, but it's just not working / it's weird. Can anyone help me?

Nikita Kalugin
  • 682
  • 2
  • 14
  • 37
  • 2
    To help, we're going to have to see what you've done and get a specific description of the errors you're experiencing. "it's just not working / it's weird" is not sufficient. – lolynns Mar 02 '18 at 06:34
  • 1
    If you just want to change the direction, you could just inverse the delta (`delta *= -1`) and then all you need to is add the `delta` to the positional value. If you want to change the direction based on the angle of collision, you could try doing [something like this example](https://stackoverflow.com/questions/13261767/java-ball-object-doesnt-bounce-off-of-drawn-rectangles-like-its-supposed-to/13263022#13263022) – MadProgrammer Mar 02 '18 at 07:12

2 Answers2

3

When balls collide, make vector connecting ball centers (N) and normalize it (uN)

Components of velocities parallel to N (normal) are exchanged (due to impulse law)

Components of velocities perpendicular to N (tangential) remain the same

To get components in given local system, use scalar and cross product:

 V1t = dot(V1, uN)  
 V2t = dot(V2, uN)  

 V1n = cross(V1, uN)
 V2n = cross(V2, uN)

after collision

V1t' = V2t
V2t' = V1t

V1n' = V1n
V2n' = V2n

To return into global system (I did not checked signs thoroughly):

V1x = V1t` * uN.X + V2n` * uN.Y 
V1y = -V1t` * uN.Y + V2n` * uN.X 

(This is essentially dot and cross products again, but I expanded expressions to show different bases)

Note that this approach is like to ball-edge collision, when N is normal to the border and you reverse only one component of velocity vector.

MBo
  • 77,366
  • 5
  • 53
  • 86
1

For your BouncingBall class, you can have a method like flipDirection(), but you can have a finer directional control by splitting it into 2 methods which filps the direction of the ball vertically and horizontally.

class BouncingBall{
    public void horizontalFlip(){
        moveX *= -1;
    }

    public void verticalFlip(){
        moveY *= -1;
    }

    //To have move control over each direction, you can have a method for each direction.
    public void moveNorth(){
        moveY = Math.abs(moveY) * -1;
    }

    public void moveSouth(){
        moveY = Math.abs(moveY);
    }

    public void moveWest(){
        moveX = Math.abs(moveX) * -1;
    }

    public void mpveEast(){
        moveX = Math.abs(moveX);
    }
}

Depending on how you want the ball to bounce off. In a simple bounce off, the balls can bounce towards 4 possible directions:

  • North West
  • North East
  • South West
  • South East

The direction of the ball to bounce off will be relative to the position of the ball it is colliding with and you do not want 2 collided balls which move in the same direction to switch direction just because they collided. Hence you need to check the positions of the 2 balls, and flipDirection() becomes insufficinet to achieve that.

if(b1.intersects(b2)){
    if(b1.getX() < b2.getX()){ // b1 above b2
        b1.moveNorth();
        b2.moveSouth();
    }
    else{
        b1.moveSouth();
        b2.moveNorth();
    }
   if(b1.getY() < b2.getY()){ // b1 at left side of b2
        b1.moveWest();
        b2.moveEast();
    }
    else{
        b1.moveEast();
        b2.moveWest();
    }
}

For example, to change direction when hitting the walls on the left and right:

if(ball.getPosX() <= 0 || ball.getPosX() >= PNL_WIDTH-Ball.SIZE)
    ball.horizontalReverse();

Same logic for verticalReverse.

user3437460
  • 17,253
  • 15
  • 58
  • 106
  • 1
    @EDWIN I have upvoted your question once again as an encourangement. This is the solution and you may accept my answer. – user3437460 Mar 02 '18 at 10:38
  • 1
    I think I already find my own solution. But anyway, thank you for your response. I'll accept it. But i have one more question. I used [this](https://ideone.com/ocFULE). And It works. But there is a small bug, sometimes the balls get stuck in the upper left corner. They begin to fight back against each other and from the edges of the window, so they do not move anywhere. I can't fix it and can't figure out why they're stuck right in the top left corner, could you help me? Here's screenshot of this https://prnt.sc/ilsd48 – Nikita Kalugin Mar 02 '18 at 12:50
  • 1
    @EDWIN It is due to the conditions you gave when the balls hit the wall. Imagine this, if you code it as "when the balls hit the wall, change direction", but if the balls are ***inside*** the wall, that condition of yours will always be true. Thus the balls keep flipping their direction endlessly. To solve it, either A) don't let the balls get into the walls, B) change your actions after the balls collide with the wall. E.g. Let them flip in only one direction till they get off the wall. So how does the balls get into the wall? When they are moving more than 1 pixel per frame, that may happen. – user3437460 Mar 02 '18 at 13:07