We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello,
I am trying to get a simple collision of 2 balls to work. Unfortunately sometimes 2 collisions (1 from the point of view of each ball) are detected and the balls get stuck together. How can I make sure only 1 collision is detected?
Thank you in advance for your time and help. Here is the code.
Cecilia
int count;
int index;
float d;
Ball ball1;
Ball ball2;
float angleBetween1;
float angleBetween2;
float distanceAngle;
float velocityAngle1;
float velocityAngle2;
PVector distance;
boolean collision;
void setup() {
size(400, 400);
background(128);
frameRate(25);
collision = false;
ball1 = new Ball(20, 40);
ball2 = new Ball(200, 300);
d = 0;
distance = new PVector(0, 0);
}
void draw() {
background(128);
ball1.ballMove();
ball1.ballBounce();
ball1.ballDraw();
ball2.ballMove();
ball2.ballBounce();
ball2.ballDraw();
if (collision == false) {
PVector distance = PVector.sub(ball1.location, ball2.location);
d = distance.mag();
if (d <= ((ball1.getDiameter()/2)+(ball1.getDiameter()/2))) {
collision = true;
println("collision");
}
}
if (collision == true) {
distanceAngle = distance.heading();
velocityAngle1 = ball1.velocity.heading();
velocityAngle2 = ball1.velocity.heading();
angleBetween1 = PVector.angleBetween(distance, ball1.velocity);
angleBetween2 = PVector.angleBetween(distance, ball2.velocity);
if (velocityAngle1 > distanceAngle) {
ball1.velocity.rotate(-(velocityAngle1*2));
ball1.velocity.mult(-1);
}
if (velocityAngle1 < distanceAngle) {
ball1.velocity.rotate(velocityAngle1*2);
ball1.velocity.mult(-1);
}
if (velocityAngle2 > distanceAngle) {
ball2.velocity.rotate(-(velocityAngle2*2));
ball2.velocity.mult(-1);
}
if (velocityAngle2 < distanceAngle) {
ball2.velocity.rotate(velocityAngle2*2);
ball2.velocity.mult(-1);
}
collision = false;
}
}
class Ball {
PVector location;
PVector velocity;
float diameter;
Ball(float tempX, float tempY) {
diameter = random(100, 120);
location = new PVector(tempX,tempY);
velocity = new PVector(3, 3.1);
}
float getDiameter() {
return diameter;
}
void ballMove() {
location.add(velocity);
}
void ballBounce() {
if (location.x + diameter / 2 > width) {
location.x = width - diameter/2;
velocity.x = velocity.x *-1;
}
if (location.x - diameter / 2 < 0) {
location.x = 0 + diameter/2;
velocity.x = velocity.x *-1;
}
if (location.y + diameter / 2 > height) {
location.y = height - diameter/2;
velocity.y = velocity.y *-1;
}
if (location.y - diameter / 2 < 0) {
location.y = 0 + diameter/2;
velocity.y = velocity.y *-1;
}
}
void ballDraw() {
fill(200, 50);
noStroke();
ellipse(location.x, location.y, diameter, diameter);
}
}
Answers
typo?
Yes, this is a typo, thank you.
Unfortunately that doesn't stop the objects from getting stuck together. Any idea why that might be?
could it be this typo? 8)
if (d <= ((ball1.getDiameter()/2)+(ball1.getDiameter()/2))) {
^ that might make it think balls have collided when they haven't, or have collided again when they were just starting to head off in different directions. would happen more if balls were quite different sizes.
Thanks for spotting another typo. But unfortunately that doesn't fix the getting stuck together issue either.
Assuming that code for the actual bounce is okay (I am not certain, but let's assume), I think what happens is that a collision is detected and the code from line 45 is executed. But then in the next iteration of the draw method the balls are still overlapping. As a result another collision is detected and the code from line 45 onwards is executed. This means a reversal of direction again so the balls are overlapping even more. And then they are stuck. Do you think this could be the problem?
Thanks for your time and help.
yes, i think that might be the problem
try adding visible vectors to the drawing so you can see where everything's going.
those collisions look wrong.
i've added some debug - it stops when it collides. the green is the current velocity, the blue is the new velocity. press a key to restart it.
NB my version of processing doesn't have pvector.heading() so i've made my own, copied from pvector source.
Thank you very much. That does highlight lots of mistakes. I think the problem is that I tried to calculate it all with vectors. I think basic trigonometry is the way forward. Or can you see a way to calculate it with vectors?
no, i think vectors will do what you need - they are only a class to make vector arithmetic easier and that's what you need.
resultant vector needs to be a reflection of the initial vector using the collision line as the mirror. which you can do with rotations. i think you may just be rotating one of the angles in the wrong direction. no obvious solution came to mind last night and i have other things to do so... it doesn't look THAT wrong tbh, like it's a sign issue or something.
Thank you very much for your help. Making the vectors visible helps a lot. I will try to solve the problem, but unfortunately have got other things to do now too.
hello, I'm new in this forum and a new Processing user. I didn't take the problem of the collision the same way you did it, especially because I'm not that confident with mathematics and the use of vector. Nevertheless, this is the way I treated the question and it seems to work. Sure, the rebound does not always look realistic. I just transfer Ball1 movement to Ball2 and vice versa. I think I probably would have to take in account the rotation of the ball... but it's a first approach and it works not so bad and I hope it could help.
Now I have a question: do anybody have an idea how to deal the same behavior with 100 balls ?
oops, it seems the copy/paste of the program lines does not work the way I imagine... The lines are there but not displayed as in the program. Is there another mean than ctrlC --> ctrlV to paste program lines to this page ?
Yup, we highlight the code block and hit CTRL+K. Then it's automatically indented 4 spaces and it's recognized as a code block!
Also, make sure to have 1 line break before and after the block, in case there's normal text before or after!
regarding the layout of the program lines:
please
Chrisir
Regarding bouncing:
I don't know about bouncing balls but bouncing one ball at walls:
I often (even in the examples) see lines like
velocity.x = velocity.x *-1;
but when the velocity is small and in the next iteration of draw() the ball is still in the area where the condition applies (bouncing area / collision area)
velocity.x = velocity.x *-1;
is called again. When we add the value to the position, the ball stutters and stays in the bouncing area forever (since value e.g. toggles between +0.5 and -0.5).
To avoid this, at least for normal walls check for left and right [upper and lower] screenborder separately and say
velocity.x = abs (velocity.x );
(abs = always positive result) for the left screenborder / wall and
velocity.x = abs (velocity.x ) * -1;
(always negative result) for the right wall. The results are always positive or always negative and can not toggle between the two as with
velocity.x = velocity.x *-1;
Good to know!
Chrisir
here is Philips Code
@ Philip
see
on
http://wiki.processing.org/w/Technical_FAQ
I had a look to the "more advanced question" and I have to digest all that stuff now before to go further. Apart creating a lot of objects a simple way, do you think this will also give the possibility to declare a common behavior such having all balls rebound each one to each other ? as this was my first idea...
yes, this is possible, there are a lot of examples or when you search the old forum.
The basic idea for multiple balls is to cluster the vars and functions for one ball in a class
this class is then the blue print for all your balls.
these balls you have in an array (of type class Ball)
so when you move the balls, you just loop over the array and tell each balls to move
here is a approach with an arraylist (no collision yet)
Thank you Chrisir for your help ! it is of course not as to deal with the squaring of the circle, but I think I still have a lot to learn before playing billiards with all that balls... i'll be back later with some progress...
This is something approaching to what I hope to have: creating n balls and have collisions between all (and the window bounds). nevertheless, I still have the issue that some rebound against the others and some do not ! Do you have an idea why ? And to help solving the problem, do you know if and how is it possible to have the number of each ball printed in it ?
here is the new code :
That is a cool bump simulation. I've got 1 online too! Check it out:
http://studio.processingtogether.com/sp/pad/export/ro.91xkuWl51J$Vp/latest
Thanks GTL ! With the code I proposed you can also change the number of balls at line 4 -> final int NumeroBalle = 5; and increase it up 100 even more, in that case you have to inactivate the displayLine() at line 55, and reduce the radius at line 30 to random(2,3)... amazing too... The one you've posted is cool too ! Do you have the code for this one ? ... and any idea with my question why some bumps some not ?
Ooops ! I found your code, as far as it was directly under the "game" and didn't scroll down the page before to answer, but play the game...