While Ben's suggestion will very significantly reduce the number of comparisons you need to make from n*n*n to n*n, you can improve things still further.
Both collisions and line drawing in your example are symmetric. In other words, if spot A collides with spot B, then spot B must also have collided with spot A. You can therefore halve the number of line drawings and collision detections you need to make. In fact, it is slightly less than half since you never have to compare a spot with itself. An easy way to implement this is to pass an index number of the current spot being tested to your
collision() and
lines() methods. These methods need only compare with the remaining untested spots in your array.
A second, minor improvement, is to remove the stroke and fill settings from inside your for loops since they do not change in response to the loop iterations. While this will have a very minor effect in this case, it is good practice separate code that depends on each loop iteration from that which applies to all loop iterations.
There is also slightly more subtle bug introduced by Ben's more efficient drawing code. Because the code for drawing an uncollided spot is in a different method to the code for drawing a collided spot, a spot that is drawn as collided, can get redrawn as uncollided as the for loop in
draw proceeds. A more object-oriented solution would be to store as part of the state of each spot, whether or not it is in collision with anything, and then modify Spot's [tt]display/tt] method appropriately.
Code incorporating all of the above is shown below:
Quote:int numSpots = 10;
Spot[] spots = new Spot[numSpots];
void setup(){
size(400,400);
smooth();
noStroke();
for(int i = 0; i<spots.length; i++)
{
float x = random(0,width);
float y= random(0,height);
float rate = 1.5 + i*random(0.15,0.3);
spots[i] = new Spot(x,y,40,rate);
}
}
void draw(){
fill(0,310);
rect(0,0,width,height);
fill(255);
for(int i=0; i<spots.length; i++){
spots[i].move();
spots[i].collision(i); // Test for collisions before drawing.
spots[i].display();
spots[i].lines(i);
}
}
class Spot{
float x, y;
float rad;
int dirY=1;
int dirX=1;
float speed;
boolean hasCollided;
Spot(float xpos, float ypos,float radius, float sp){
x=xpos;
y=ypos;
rad=radius;
speed=sp;
hasCollided = false; // Records the spot's collision status
}
void move(){
y= y+speed * dirY*0.15 ;
x= x+speed * dirX ;
if(y>=height || y<=0){
dirY =dirY * -1;
}
if(x>=width || x<=0){
dirX =dirX * -1;
}
}
void display(){
fill(255);
ellipse(x,y,rad,rad);
if (hasCollided){
fill(255,9,9);
ellipse(x, y, 30, 30);
hasCollided = false; // Reset collision status after drawing.
}
}
void collision(int start)
{
for (int i = start+1; i< numSpots; i++){
if (dist(x, y, spots[i].x, spots[i].y) <= (rad + spots[i].rad) / 2){
// Label the pair of spots as having collided.
this.hasCollided = true;
spots[i].hasCollided = true;
}
}
}
void lines(int start){
strokeWeight(0.3);
stroke(255) ;
for (int i = start+1; i< numSpots; i++){
if (spots[i] != this){
line(x, y, spots[i].x, spots[i].y);
}
}
}
}