Nature of Code (Particle System with wind and gravity)

This week's homework focused on particle systems. I used my hot air ballons with another set of smaller red balloons. Wind and gravity are applied and the red balloons are passed in through the new principle of inheritance that we are learning.

ArrayList<ParticleSystem> systems;
PImage img;

void setup() {
  size(600, 800, P2D);
  systems = new ArrayList<ParticleSystem>();
  img = loadImage("clouds.jpeg");
}

void draw() {
  background(255);
  image(img, 0, 0);

  PVector gravity = new PVector (0, 0.05);

  for (ParticleSystem ps: systems) {
    ps.applyForce(gravity);
    ps.run();
    ps.addParticle();
    if (keyPressed) {
      if (key == 'w') {
        PVector wind = new PVector (0.05, 0);
        ps.applyForce(wind);
      }
    }
  }
}

  void mousePressed() {
    systems.add(new ParticleSystem(1, new PVector(mouseX, mouseY)));
  }

class RedBalloon extends Particle {

  RedBalloon(PShape _s, PVector l) {
    super(_s,l);
  } 

  void display() {
    shape(s, location.x, location.y, 15, 15); //want to just change size of red balloon

  }
}

class Particle {
  PVector location;
  PVector velocity;
  PVector acceleration;
  PVector gravity;
  float lifespan;
  PShape s;

  Particle(PShape _s, PVector l) {
    s =_s;
    acceleration = new PVector(0, 0.05);
    velocity = new PVector(random(-1, 1), random(-2, 0));
    location = l.get();  //making a copy
    lifespan = 155.0;
  }

  void applyForce(PVector force) {
   acceleration.add(force); 
  }

  void run() {
    update();
    display();
  }

  // Method to update location
  void update() {
    velocity.add(acceleration);
    location.add(velocity);
    acceleration.mult(0);  //if acceleration is steady on, velocity will continue to ramp up  and location will fly 
    lifespan -= 2.0;
  }

  // Method to display
  void display() {
    stroke(0, lifespan);
    strokeWeight(2);
    fill(100, lifespan);
    shape(s, location.x, location.y, 50, 50);  //shape(s, location.x, location.y, 125, 125);
  }

  // Is the particle still useful?
  boolean isDead() {
    if (lifespan < 0.0) {
      return true;
    } 
    else {
      return false;
    }
  }
}

class ParticleSystem {

  PShape balloon = loadShape("balloon.svg");
  PShape red_balloon = loadShape("red_balloon.svg");

  ArrayList<Particle> particles;    // An arraylist for all the particles
  PVector origin;        // An origin point for where particles are birthed

  ParticleSystem(int num, PVector v) {
    particles = new ArrayList<Particle>();   // Initialize the arraylist
    origin = v.get();                        // Store the origin point
    for (int i = 0; i < num; i++) {
      Particle p = new Particle (balloon, origin);
      particles.add(p);    // Add "num" amount of particles to the arraylist
    }
  }

  void run() {
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      if (p.isDead()) {
        particles.remove(i);
      }
    }
  }

  void addParticle() {
    float r = random(1);
    if (r < 0.7) {
      particles.add(new Particle(balloon, origin));
    }
    else {
      particles.add(new RedBalloon(red_balloon, origin));
    }
  }

  void applyForce(PVector force) { 
    for (Particle p : particles) {
     p.applyForce(force);
    } 
  }

    // A method to test if the particle system still has particles
    boolean dead() {
      if (particles.isEmpty()) {
        return true;
      } 
      else {
        return false;
      }
    }
  }