We are about to switch to a new forum software. Until then we have removed the registration on this forum.
dear all, i'm an absolute beginner in processing and i'm struggling with a (simple?) problem. please bare with me, as I'm sure the code is catastrophic and a lot of my terminology here is wrong :)
basically i'm trying to achieve a simple rectangle collision, using an array and a class. it almost works, but sometimes, rectangles don't collide/rebound, but pass through one another.. i have no clue why this is.
i'd be gracious for any help!
Bouncer[] bouncers = new Bouncer[0];
float resize = 30;
float minsize = 2;
float maxsize = 50;
float freq = 440;
float amp = 0;
float globspeed = 3.;
float boxes = 5;
float margin = 5;
void setup() {
//frameRate(10);
size(700, 400);
resize = minsize;
pmouseY = mouseY;
}
void draw() {
background(255);
if (mousePressed) {
resize += 2;
noStroke();
rectMode(CENTER);
fill(50);
resize = constrain(resize, minsize, maxsize);
rect (mouseX, mouseY, resize, resize);
}
for (int i = 0; i < bouncers.length; i++ ) {
bouncers[i].move();
bouncers[i].create();
bouncers[i].collide();
}
float onebox = ((width - ((boxes+1)*margin)) / boxes );
for (float i = 1; i <= boxes; i++ ) {
rectMode(CORNER);
noStroke();
fill(50);
rect((i-1.)*(onebox+margin)+margin, height-20, onebox, 20-margin);
}
}
void mouseReleased() {
Bouncer anotherone = new Bouncer(mouseX-resize/2, mouseY-resize/2, resize, resize-resize/2*(globspeed*-1), bouncers.length, 50);
bouncers = (Bouncer[]) append(bouncers, anotherone);
resize = minsize;
}
here's my class declaration:
class Bouncer {
float posX;
float posY;
float size;
float speed;
//SinOsc sine;
float freq = 440;
float gravity = 1;
int iam;
float col;
Bouncer(float posX_, float posY_, float size_, float speed_, int iam_, float col_) {
posX = posX_;
posY = posY_;
size = size_;
speed = speed_/10;
iam = iam_;
col = col_;
}
void create() {
rectMode(CORNER);
noStroke();
fill(col);
rect(posX, posY, size, size);
//println(iam);
}
void collide() {
for (int io = 0; io < bouncers.length; io++) {
float x1 = bouncers[iam].posX;
float y1 = bouncers[iam].posY;
float s1 = bouncers[iam].size;
float x2 = bouncers[io].posX;
float y2 = bouncers[io].posY;
float s2 = bouncers[io].size;
if (x1+s1/2 >= x2-s2/2 && x1-s1/2 <= x2+s2/2)
{
if (y1+s1 >= y2 && y1 <= y2+s2) {
bouncers[iam].speed *= -1;
bouncers[io].speed *= -1;
bouncers[io].col = 150;
}
}
}
}
void move() {
posY = posY + speed;
if (posY > height-size-20) {
speed *= -1;
posY = height-size-20;
} else if (posY <= 0) {
posY = 1;
speed *= -1 ;
}
}
}
Answers
checking box 1 (i = 1 on line 32) against box 2 (io = 2 on line 32 of the class). they collide, so change the direction of both of them.
milliseconds later you compare box 2 (i = 2 on line 32) against box 1 (io = 1 on line 32 of the class). they are STILL colliding (box 1 hasn't moved, box2 has moved one step, using its new speed, changed above) so change the direction of both...
see the problem?
thanks so much koogs for jumping in.. i'm not sure if i understand... as soon as i change both their directions (line 43+43) – shouldn't they stop colliding?
got another hint for me novice? thanks (:
You change the directions at that point but you don't move them so they are still colliding.
You then move the second one, but if it's moving slower than the first the new position could still be colliding.
For instance: If the first one is moving at 10 units per click then the overlap on the first check might be 8 units. You swap directions and move the second block before retesting. If that's only moving 5 units per click it'll never escape.
This stuff is tricky.
@benniii --
If two shapes overlap deeply before changing direction, they will "vibrate" -- changing direction constantly, but never escaping. Different strategies to avoid these kinds of problems:
...etc.
thanks for these tips, guys... jeee... i have to admit, i have not a clue as for how to do this. i wouldn't have imagined that this simple "bounce and collision" task was such a challenge... mh
It might be enough to only change the direction of one of the two colliding items, rather than both.
Or stop checking both A against B and then B against A by only checking items that come later in the list than the one currently being checked.
thanks a ton for all your help, folks! i think i was kind of able to solve it thanks to the both of your tips... i'm only changing the direction for one rectangle and i'm waiting several frames after collision.
oh, there's so much to learn!
This is a collision code using circles. I found this code at: https://processing.org/examples/circlecollision.html
However, when you add more objects to it, and their radius are alike, they will experience the vibration/jittering that @jeremydouglass mentioned. Here is a slightly modified version of the code to see the effect. Let it run for few seconds or a cpl of minutes to see the jittering effect.
New objects are added with random radius within a range of 50% to 100% of the value of R. The value of n defines the number of objects to instantiate in the scene.
I like method #2 described by Jeremy above. One would need to consider extreme cases were multiple bouncing occurs. I will keep a list of overlapping object pairs or an alternative is for each object to have a list of what other objects it has experienced overlapped with.
Kf
Here is the solution for the previous example... using circles. If you disabled the money line, you will see the undesirable vibration effect.
EDITED ##############
Kf
This issue is discussed in githb: https://github.com/processing/processing-docs/issues/492
Kf