2

I am creating a project of bouncing balls.

The only problem with my project is with collision resolution when two balls intersect with each other.Collision detection is fine as when two balls intersect they bounce back but then they keep colliding again and again.When the balls collide with the walls they bounce correctly but I don't know why when they collide with each other there is a problem.

I have tried various code but still can't get it.

How can i do this ?

You can take help of this link as did I..

Ball to Ball Collision - Detection and Handling

Here is my code :

package com.example.bouncer;


import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.provider.SyncStateContract.Constants;
public class Ball {

private Point p;   //Point p:Represents the x and y position of the Ball
private int c;     //Represents the color of the Ball
private int r;      //Represents the Radius of the Ball.
private int dx;             //Integer dx:Represents the change in x position of ball  
                            // Integer dy:Represents the change in y position of ball
private int dy;
private Paint paint;      //Android Object holding the color for drawing on the canvas
public Ball(int x,int y,int col,int radius)
{
    p=new Point(x,y);
    c=col;
    r=radius;
    paint=new Paint();
    dx=0;
    dy=0;
}
public int getX()
{return p.x;
}
public int getY()
{
    return p.y;
}
public int getRadius()
{return r;
}
public Paint getPaint()
{return paint;
}
public void setColor(int col)
{c=col;
}
public void goTo(int x,int y)
{p.x=x;
p.y=y;
}
public void setDX(int speed)
{dx=speed;
}
public void setDY(int speed)
{
    dy=speed;
}
public void move()
{
    p.x=p.x+dx;
    p.y=p.y+dy;
}
public void bounce(Canvas canvas)       //COLLISION DETECTION AND RESOLUTION WITH WALLS
{
    move();
    if(p.x>canvas.getWidth()|| p.x<0)
    {

        dx=dx * -1;
    }
    if(p.y>canvas.getWidth()|| p.y<0)
    {

        dy=dy * -1;
    }


    }


    public void bounceoff(Ball b)          //BALL TO BALL COLLSION DETECTION
    {
       float x = b.getX() - p.x;
       float y = b.getY() - p.y;
       float distanceSquared = x*x + y*y;
       float radius = b.getRadius()+r;
       float radiusSquared = radius*radius;
       if (distanceSquared <= radiusSquared)
       {
            dx=dx * -1;
            dy=dy * -1;

       }
    }
}

AnimationView.java

package com.example.bouncer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
public class AnimationView extends View{
  private final int FRAME_RATE=15;
  private Paint paint;
  private Handler h;
  Ball myball;
  Ball greenball;
  Ball redball;
    public AnimationView(Context context,AttributeSet attrs) {
        super(context,attrs);
        // TODO Auto-generated constructor stub
        h=new Handler();
        paint=new Paint();
        paint.setColor(Color.BLUE);
        myball=new Ball(100,100,Color.BLUE,50);
        greenball=new Ball(200,200,Color.GREEN,50);
        redball=new Ball(50,400,Color.RED,50);
        myball.setDX(10);
        myball.setDY(10);
        greenball.setDX(-20);
        greenball.setDY(-15);
        redball.setDX(5);
        redball.setDY(-5);

    }
    protected void onDraw(Canvas c)
    {
        myball.bounce(c);
        greenball.bounce(c);
        redball.bounce(c);
        myball.bounceoff(myball);
        greenball.bounceoff(greenball);
        redball.bounceoff(redball);
        c.drawCircle(myball.getX(), myball.getY(),myball.getRadius(), myball.getPaint());
        c.drawCircle(greenball.getX(), greenball.getY(),greenball.getRadius(), greenball.getPaint());
        c.drawCircle(redball.getX(), redball.getY(),redball.getRadius(), redball.getPaint());

        h.postDelayed(r, FRAME_RATE);

    }
    private Runnable r=new Runnable()
    { public void run()
    { invalidate();
    }
    };
    }

If you want my complete project code check out the link.. https://stackoverflow.com/questions/22892736/balls-keep-colliding-again-and-again-android

Community
  • 1
  • 1
  • If you want my complete project code check out the link... http://stackoverflow.com/questions/22892736/balls-keep-colliding-again-and-again-android –  Apr 07 '14 at 11:27

3 Answers3

0

I think that you can get false collisions with the criteria you use to detect ball to ball collision. If AB is the vector between the centers of balls A and B and rA is the radius of A and rB the radius of B then you can use this criteria to check if the balls collide

|AB| < rA + rB

Where |AB| means the length of the vector AB

An optimized way to calculate this (avoiding the costly square root calculation) is

int xDiff = b.getX()-p.x;
int yDiff = b.getY()-p.y;
int radii = b.getRadius() + r;
if ( ( xDiff * xDiff + yDiff * yDiff ) < radii * radii ) {
    // Collision response. Change the balls velocity

Also, a couple of side notes.

  1. I think it would be best to take move out of bounce so that you first move all the balls and then check if any of them collodied either with another ball or with a wall.

  2. Your collision response (what happens when the balls collide) i.e. just reversing the direction of the balls will only work correctly if the balls velocities are the same except for the sign (e.g. vA = 1m/s, vB = -1m/s). In other cases the balls won't bounce as expected.

Simon
  • 6,293
  • 2
  • 28
  • 34
  • Actually the distance between two points is the length of the vector between them which is `sqrt(xDiff^2 + yDiff^2)` so the distance between the two centers is not `2r` – Simon Apr 07 '14 at 10:52
  • @Simon..You can see in my program the block of code which I have added as comment at the last..It is almost similar in logic to what you have written and it also does not produces the expected output..thanks for ur effort.. –  Apr 07 '14 at 11:17
0

I will look at it properly later on, but at first glance I don't like:

if((Math.abs(b.getX()-p.x)<b.getRadius()+r)&& (Math.abs(b.getY()-p.y)<b.getRadius()+r))

You need something like:

diffX = b.getX() - p.x;
diffY = b.getY() - p.y;
rad1 = this.getRadius();
rad2 = b.getRadius();
if((diffX * diffX + diffY * diffY) < (rad1 * rad1 + rad2 * rad2))

[Edited because balls have different radii]

Rewind
  • 2,554
  • 3
  • 30
  • 56
  • You can see in my program the block of code which I have added as comment at the last..It is almost similar in logic to what you have written except the 4 which u added..That code in comment also does not produces the expected output..I will be grateful to you if you look at it later on and help me in my problem.. –  Apr 07 '14 at 11:15
  • If you want my complete project code..check out the link..http://stackoverflow.com/questions/22892736/balls-keep-colliding-again-and-again-android –  Apr 07 '14 at 11:25
0

The problem is that when you detect balls collision, you move both balls a point up and left. This causes the balls to move together and not to bounce off.

To achive the desired effect the ball on the left should go -1 and the one on the right +1. Same thing applies for vertical axis, the upper ball should get -1 and the bottom one +1

public void bounceoff(Ball b)          //BALL TO BALL COLLSION DETECTION
{
   float x = b.getX() - p.x;
   float y = b.getY() - p.y;
   float distanceSquared = x*x + y*y;
   float radius = b.getRadius()+r;
   float radiusSquared = radius*radius;
   if (distanceSquared <= radiusSquared)
   {
       dx=dx * -1;
       dy=dy * -1;
       b.setDY(b.getDX()*-1);
       b.setDY(b.getDY()*-1);

       if (x<b.getX()){
           x = x-1;
           b.setX(b.getX()+1);
       }else{
           x = x+1;
           b.setX(b.getX()-1);
       }     
       if (y<b.gety()){
           y = y-1;
           b.setY(b.getY()+1);
       }else{
           y = y+1;
           b.setY(b.getY()-1);
       }     

   }
}

You should also add 2 setters in the Ball class:

public void setX(int x)
{
    p.x = x;
}
public void setY(int y)
{
    p.y = y;
}

public int getDX()
{
    return dx;
}
public int getDY()
{
    return dy;
}

And the onDraw needs some work:

protected void onDraw(Canvas c)
{
    // ball bouncing on walls
    myball.bounce(c);
    greenball.bounce(c);
    redball.bounce(c);

    // balls bouncing on each other
    myball.bounceoff(redball);
    myball.bounceoff(greenball);
    redball.bounceoff(greenball);

    // draw balls
    c.drawCircle(myball.getX(), myball.getY(),myball.getRadius(), myball.getPaint());
    c.drawCircle(greenball.getX(), greenball.getY(),greenball.getRadius(), greenball.getPaint());
    c.drawCircle(redball.getX(), redball.getY(),redball.getRadius(), redball.getPaint());

    h.postDelayed(r, FRAME_RATE);
}
gtsouk
  • 5,208
  • 1
  • 28
  • 35
  • thnks for ur answer...can u suggest me the code for that? –  Apr 09 '14 at 13:27
  • actually the balls does bounces nd then collides again and again –  Apr 09 '14 at 13:28
  • Error in b.x(x cannot be resolved or is not a field) –  Apr 09 '14 at 13:45
  • @user3503165 use a setter instead, or create one if you don't have one ;) – Joffrey Apr 09 '14 at 13:46
  • You have to add 2 setter in your class. See my update – gtsouk Apr 09 '14 at 13:53
  • no...the balls keep shifting slightly left-right-left-right-left-right and move in one direction nd finally move out of screen.. –  Apr 09 '14 at 14:07
  • rest all my program is correct except bounceoff() method..if i don't call bounceoff() method the balls randomly move over the screen bouncing on colliding wid walls as expected but doesn't bounce on colliding wid each other –  Apr 09 '14 at 14:10
  • Ok i changed the other ball direction too. see update – gtsouk Apr 09 '14 at 14:13
  • the balls keep shifting slightly left-right-left-right-left-right and move in one direction nd finally move out of screen..this time they move along x axis..i am calling bounce() method before bounceoff()..u can see my complete unupdated code at http://stackoverflow.com/questions/22892736/balls-keep-colliding-again-and-again-android –  Apr 09 '14 at 14:39
  • Can you show me the loop that calls bounce() and bounceOff()? – gtsouk Apr 09 '14 at 14:53
  • Go to http://stackoverflow.com/questions/22892736/balls-keep-colliding-again-and-again-android nd see ondraw() method in AnimationView.java –  Apr 09 '14 at 14:55
  • try the onDraw in my answer above – gtsouk Apr 09 '14 at 14:59
  • i have added AnimationView.java here only –  Apr 09 '14 at 14:59
  • thanks for ur time gtsouk!i updated onDraw as u said...The problem now is that the moment ball intersect each other they start bouncing up down at very high speed blinking in between..nd sometimes when they intersect each other from left-right they pass away without bouncing..still not the expected output –  Apr 10 '14 at 05:30