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>();
buoys.add(new buoy(3*width/4, height/2, 100));
buoys.add(new buoy(mouseX, mouseY, 101));
//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[0]; //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
waves.addAll(buoywaves);
}
}