 # Double hit on object collision and repeat trigger

Hello processing forum I’m making a small program that moves circles (‘buoys’) around the screen that are then triggered by expanding circles (‘waves’) in turn making more waves of their own. Waves have random speeds.

I’ve tried to make an MCVE below with a stationary test buoy and one that you move with the mouse.

I have 3 problems that I can’t figure out.

Problem 1: Each wave triggers each buoy twice when it hits, I’ve tried to resolve this by tracking which buoys the waves have hit and checking that before triggering

Problem 2: A slightly different problem, I would like each wave to only trigger a buoy once, I thought the solution for problem 1 would fix this also Problem 3: The collision detection algorithm I am using is patchy and because both the waves and buoys are moving sometimes it will not trigger. Is there a better way to do this? EDIT: I’m going to explore this as a solution? https://stackoverflow.com/questions/49722061/processing-how-to-detect-collisions-when-one-object-is-traveling-too-fast

Any help appreciated!

``````import java.util.Iterator;

ArrayList<Wave> waves = new ArrayList<Wave>();
int time;

void setup() {
size(800, 800);
}

void draw() {
background(0);
//make buoys and add to arraylist
ArrayList<buoy> buoys = new ArrayList<buoy>();
//display buoys
for (buoy b : buoys) {
b.update();
}
//make waves
makeWaves();
//check if waves hit buoys
checkHits(buoys);
}

class buoy {
float xpos, ypos;
int hits, level, dia, id;
buoy ( float x, float y, int i) {
xpos = x;
ypos = y;
id = i;
dia = 30;
}
void update() {
noStroke();
fill(255, 0, 0);
ellipse(xpos, ypos, dia, dia);
}
}

class Wave {
float xpos, ypos, maxdia, dia, speed, setf;
color colour;
int alphalevel, origin, id;
int[] hitbuoys;

Wave ( float x, float y, float sd, float md, float s, float sf, color c, int o) {
xpos = x;
ypos = y;
maxdia = md;
dia = sd; //set start diameter
speed = s;
setf = sf; //set fade on/off
alphalevel = 255;
colour = c;
origin = o; //set origin of wave for big waves origin is 0 for bouywaves it's bouy.id
hitbuoys = new int; //array to track buoys this wave has already triggered
}
void update() {
if ( setf > 0) {
alphalevel = int(map( dia, 0, maxdia, 255, 0));
}
strokeWeight(5);
noFill();
stroke(color(colour, alphalevel));
ellipse(xpos, ypos, dia, dia);
dia += speed/2;
}
}

void makeWaves() {
//make waves randomly over time
if ( millis() > time) {
waves.add(new Wave(width, height/2, 0, 2*width, random(2, 4), 1, color(0, random(40, 240), random(220, 255)), 0));
if ( random(0, 1) > 0.9) {
time = millis() + int(random(1600, 2000));
} else {
time = millis() + int(random(4000, 8000));
}
}
//display waves and delete once at max diameter
Iterator itrW = waves.iterator();
Wave waveElement = null;
while (itrW.hasNext()) {
waveElement = (Wave)itrW.next();
waveElement.update();
if (waveElement.dia > waveElement.maxdia) {
itrW.remove();
}
}
}

void checkHits(ArrayList buoys) {
//iterate through buoys
Iterator itrB = buoys.iterator();
buoy buoyElement = null;
while (itrB.hasNext()) {
//create arraylist to add buoywaves to
ArrayList<Wave> buoywaves = new ArrayList<Wave>();
buoyElement = (buoy)itrB.next();
//iterate through waves
for (Wave wave : waves) {
//check that the wave does not originate from the buoy to stop buoys triggering themselves
if (wave.origin != buoyElement.id) {
//check whether this wave has triggered this buoy before
boolean hitbefore = false;
for (int a : wave.hitbuoys) {
if (a == buoyElement.id) {
hitbefore = true;
}
}
if (hitbefore == false) {
//check if wave is hitting buoy is there a better way to do this?!? if the buoy is moving fast it can miss the wave trigger
float r=wave.dia/2;
float x=buoyElement.xpos;
float y=buoyElement.ypos;
float cx= wave.xpos, cy= wave.ypos;
float dist= (x-cx)*(x-cx)+(y-cy)*(y-cy);
if ((dist >= r*r) && (dist < (r + (wave.speed/2))*(r + (wave.speed/2)))) {
//add this buoy id to the array of buoys triggered by this wave and generate buoy waves
append(wave.hitbuoys, buoyElement.id);
buoywaves.add(new Wave(buoyElement.xpos, buoyElement.ypos, buoyElement.dia, map(wave.alphalevel, 0, 255, buoyElement.dia, 800), random(1, 2), 1, 255, buoyElement.id));
}
}
}
}
//add buoywaves to main waves arraylist
}
}
``````

It’s no solution to one of your Problems but you can save a little code if you use the dist function.
It can directly calculate the distance between two points.

``````dist(x1,y1,x2,y2)=sqrt(sq(x1-x2)+sq(y1-y2));
``````

A thing you can try is taking the velocity of the buoy and make a loop with checks every Pixel on the way.
The look will look like this

``````for(int i=0;i<=dist(x,y,vx,vy);i++){}
``````

And the point to check is.

``````x1+vx*i/dist(x,y,vx,vy),y1+vy*i/dist(x,y,vx,vy)
``````
1 Like

Thanks for this. Yes I will try and change the collision detection to something like that.

I have solved problem 1, double trigger of collision by removing the division by 2 when increasing my wave diameter during update, so `dia += speed` instead of `dia += speed/2`

I still can’t figure out why storing the id’s of buoys triggered by a wave and then checking that array before triggering isn’t working to stop repeat triggering of buoys by the same wave though.

Problem 2 solved, I wasn’t using append properly, so `wave.hitbouys = append(wave.hitbuoys, buoyElement.id);` instead of just `append(wave.hitbuoys, buoyElement.id);`