> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.WIqHwnJ0aec/rev.1152
 * 
 * authors: 
 *   Marvin
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



ArrayList<ArrayList<Particle>> particles; //2D ArrayList containing the particles
int space; //Space between the particles
int canvasSize; //Size of the canvas, assuming square canvas
 
void setup() {
    size(800, 800);
    background(20);
     
    particles = new ArrayList();
    space = 40;
    canvasSize = max(width, height);
     
    //Create particles
    for (int i = -2 * space ; i <= canvasSize + space; i += space) {
        ArrayList<Particle> pList = new ArrayList();
        for (int j = -2 * space ; j <= canvasSize + space; j += space) {
            pList.add(new Particle(i, j));
        }
        particles.add(pList);
    }
     
    //Direction vectors of the neighbours
    //Using only the left, top and top right neighbour to avoid double or crossing lines
    var xArray = [-1, 0, 1];
    var yArray = [0, -1, -1];
 
    for (int i = 0; i < particles.size(); i++){
        ArrayList<Particle> pList = particles.get(i);
        for (int j = 0; j < pList.size(); j++) {
            Particle p = particles.get(i).get(j);
             
            //Iterate through neighbours
            for (int k = 0; k < min(xArray.length, yArray.length); k++) {
                int x = i - xArray[k];
                int y = j - yArray[k];
                 
                //Set neighbour if it exists
                if (x > 0 && y > 0 && x < particles.size() && y < pList.size()) {
                    p.neighbours.add(particles.get(x).get(y));
                }
            }
        }
    }
} 
 
void draw() {
    background(20);
     
    //Iterate through particles and update them
    for (ArrayList pList : particles) {
        for (Particle p : pList) {
            p.update();
             
            //Draw connections between neighbours
            for (int i = 0; i < p.neighbours.size(); i++) {
                Particle n = p.neighbours.get(i);
             
                //Set some value between 0 and 255 depending the x and y position of the line
                int c1 = ((p.x + n.x / 2) / canvasSize) * 255;
                int c2 = ((p.y + n.y / 2) / canvasSize) * 255;
  
                //Draw the connection
                stroke(color(255, c1, c2));
                strokeWeight(1.0f);
                line(p.x, p.y, n.x, n.y);
            }
        }
    }
}
public class Particle {
    float cx, cy; //Center position
    float x, y; //Current position
    float rx, ry; //Radii
    float rT; //Time in ms to complete one revolution
    float size; //Size of the particle, doesn't matter unless you draw it
     
    ArrayList<Particle> neighbours; //Contains left, top and top right neighbour if existent
     
    public Particle(float x, float y) {
        this.cx = x;
        this.cy = y;
         
        this.size = 2;
         
        this.rx = 15;
        this.ry = this.rx;
         
        this.rT = 500;
         
        this.neighbours = new ArrayList();
    }
     
    public void update() {
        float t = millis()/rT;
         
        //Shift the period depending on the postion
        t+= (cx/100)*PI + (cy/100)*PI;
         
        x = (int)(cx + rx * cos(t));
        y = (int)(cy + ry * sin(t));
    }
     
    public void draw() {
        //Draw the track of the particle
        noFill();
        stroke(255, 20);
        ellipse(cx, cy, rx*2, ry*2);
 
        //Draw the actual particle
        noStroke();
        fill(200);
        ellipse(x, y, size, size);
    }
}