Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niekboersen/6a4b1f0efe1df30654fa9e88c85ba64f to your computer and use it in GitHub Desktop.
Save niekboersen/6a4b1f0efe1df30654fa9e88c85ba64f to your computer and use it in GitHub Desktop.
Mountains mountains = new Mountains();
PImage leavepic, snowflakepic1, snowflakepic2, grasspic;
Rain rain = new Rain(); //the particle system that spawns the individual particles
Sun sun= new Sun();
int ParticleNumber = 1; //number of particles added per cycle
int season=1; // 1summer,2spring,3winter,4fall
int wind = 2*season;
float time;
Flock flock;
int numFrames = 24; // The number of frames in the animation
PImage[] images = new PImage[numFrames];
Snowflake[] snowflakes= new Snowflake[50];
boolean wheater=false;
color summercolor = color(255, 204, 0);
color fallcolor = color(244, 22, 1);
color wintercolor = color(244, 22, 1);
color springcolor = color(244, 22, 1);
color currentcolor= color(212, 11, 22);
Tree my_tree1;
Tree my_tree2;
void setup() {
size(1200, 800);
flock = new Flock();
my_tree1 = new Tree(width*0.75, height-50, height/5, -HALF_PI);
my_tree2 = new Tree(width/4, height-30, height/5, -HALF_PI);
leavepic = loadImage("leave.png");
snowflakepic1 = loadImage("snowflakepic1.png");
snowflakepic2 = loadImage("snowflakepic2.png");
grasspic=loadImage("grass.png");
image(grasspic, 0, 400, width, 400);
mountains.drawMountain();
for (int i=0; i<numFrames; i++) {
images[i]=loadImage("foto"+i+".png");
}
for (int i = 0; i < 10; i++) {
flock.addBoid(new Boid(width/2, height/2));
}
for (int i = 0; i < snowflakes.length; i ++) { //For loop for creating all the snowflakes in the array
if (random(0, 2) < 1) {
snowflakes[i] = new Snowflake1(random(width), random(height), random(15, 30), random(20, 50), random(0, 100), random(-0.03, 0.03), random(0.5, 2.5));
} else {
snowflakes[i] = new Snowflake2(random(width), random(height), random(15, 30), random(20, 50), random(0, 100), random(-0.03, 0.03), random(0.5, 2.5));
}
}
}
void keyPressed(){
season++;
if(season==5){
season=1;
}
}
void draw() {
background(255);
println(frameRate);
// mountains.drawMountains();
image(grasspic,0,600,width,200);
sun.display();
sun.update();
my_tree1.draw();
my_tree2.draw();
flock.run();
if (season==2) {
}
for (int i = 0; i < snowflakes.length; i ++) {
snowflakes[i].display();
snowflakes[i].move();
}
if (season==4) {
noStroke();
fill(255, 100);
rain.addParticles(ParticleNumber, new PVector(random(width), 0), false);
rain.rainShower();
}
}
class Flock {
ArrayList<Boid> boids; // An ArrayList for all the boids
Flock() {
boids = new ArrayList<Boid>(); // Initialize the ArrayList
}
void run() {
for (Boid b : boids) {
b.run(boids); // Passing the entire list of boids to each boid individually
}
}
void addBoid(Boid b) {
boids.add(b);
}
}
class Mountains {
float m[] = new float[1200];
float yoff = 0;
float yincrement = 0.005;
float noiseVar = 1;
color mountaincolor = color(51, 153, 51);
Mountains() {
}
void drawMountain() {
for (int i=0; i<width; i++) {
m[i] = noise(yoff)*height;
yoff += yincrement;
}
}
void drawMountains() {
for (int i=0; i<width; i++) {
stroke(mountaincolor);
fill(mountaincolor);
line(i, m[i], i, height);
}
}
}
class Rain {
ArrayList raindrops = new ArrayList(); //dynamic array with add and remove
int MaxNumber = 200; //max number of raindrops;
Rain() {
}
void rainShower() {
for (int i = raindrops.size() - 1; i >= 0; i--) { //cycle backwards to account for ArrayList deleting particles
Raindrop raindrop = (Raindrop) raindrops.get(i); //Niek waarom moet die raindrop tussen haakjes erbij?
raindrop.run();
if (raindrop.dead()) {
raindrops.remove(i);
}
if (raindrop.hitGround()) {
addParticles(raindrop.numCh, raindrop.location, true);
raindrop.location.y = 0 - raindrop.dropHeight;
raindrop.location.x = random(width);
raindrop.numCh = int(random(1, 3));
}
}
}
void addParticle(PVector location_) {
raindrops.add(new Raindrop(new PVector(random(width), 0), false));
}
void addParticles(int no_, PVector loc_, Boolean timed_) {
if (raindrops.size() < MaxNumber && !timed_) {
for (int i = 0; i < no_; i++) {
raindrops.add(new Raindrop(loc_, timed_));
}
} else {
if (timed_) {
for (int i = 0; i < no_; i++) {
raindrops.add(new Raindrop(loc_, timed_));
}
}
}
}
}
class Raindrop {
//vars
PVector location, velocity, acceleration, gravitation;//initialises all necessary vectors
float velocityMax=5, drag;
int dropWidth = 2; //width
int dropHeight = 8; //height
Boolean timed; //determines whether particle has lifespan
int timer = 5; //cycles that timed particles live; magic no. = 5;
int numCh = 3; //number of spawns upon hitting ground
//Boolean mouseMode = false; //experimented with adding mouse control
Raindrop(PVector location_, Boolean timed_) { //PVector as location to be able to adapt direction and speed etc.
location = location_.get(); //location vector
acceleration = new PVector(0, 0); //acceleration vector
gravitation = new PVector(0.05, 1); //gravity constant
timed = timed_;
if (timed) {
velocity = new PVector(random(-3, 3), random(-5, -3));
} else {
velocity = new PVector(0, 0);
}
}
void run() {
if (timed) {
timer--;
}
update();
display();
}
void update() {
if (!timed) {
acceleration.add(gravitation);
}
velocity.add(acceleration);
velocity.limit(velocityMax);
location.add(velocity);
}
boolean hitGround() {
if (location.y >= height ) {
return true;
} else {
return false;
}
}
void display() {
noStroke();
fill(104);
rect(location.x, location.y, dropWidth, dropHeight);
}
boolean dead() {
if (timer < 0) {
return true;
} else {
return false;
}
}
}class Snowflake { // creates the class
float x, y, r, p, w, h, s;
Snowflake (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) { //The constructor of the class
x = tempX; //Defining the variables
y = tempY;
r = rotation;
p = randomrot;
w = tempW;
h = tempH;
s = speed;
}
void move() {
r=r+p;
x = x + random(-0.5, 0.5);
y = (y + s) % height;
x = constrain(x, 0, width);
}
void display() {
}
}
class Snowflake1 extends Snowflake {
PImage im1;
Snowflake1 (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) {
super(tempX, tempY, tempW, tempH, rotation, randomrot, speed);
im1 = snowflakepic1;
}
void display() {
if (season==3) { //winter
pushMatrix();
translate(x, y);
rotate(r);
// image(im1, 0, 0, w, w);
popMatrix();
}
}
}
class Snowflake2 extends Snowflake {
PImage im2;
Snowflake2 (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) {
super(tempX, tempY, tempW, tempH, rotation, randomrot, speed);
im2 = snowflakepic2;
}
void display() {
if (season==3) { //winter
pushMatrix();
translate(x, y);
rotate(r);
image(im2, 0, 0, w, w);
popMatrix();
}
}
}
class Snowflake { // creates the class
float x, y, r, p, w, h, s;
Snowflake (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) { //The constructor of the class
x = tempX; //Defining the variables
y = tempY;
r = rotation;
p = randomrot;
w = tempW;
h = tempH;
s = speed;
}
void move() {
r=r+p;
x = x + random(-0.5, 0.5);
y = (y + s) % height;
x = constrain(x, 0, width);
}
void display() {
}
}
class Snowflake1 extends Snowflake {
PImage im1;
Snowflake1 (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) {
super(tempX, tempY, tempW, tempH, rotation, randomrot, speed);
im1 = snowflakepic1;
}
void display() {
if (season==3) { //winter
pushMatrix();
translate(x, y);
rotate(r);
// image(im1, 0, 0, w, w);
popMatrix();
}
}
}
class Snowflake2 extends Snowflake {
PImage im2;
Snowflake2 (float tempX, float tempY, float tempW, float tempH, float rotation, float randomrot, float speed) {
super(tempX, tempY, tempW, tempH, rotation, randomrot, speed);
im2 = snowflakepic2;
}
void display() {
if (season==3) { //winter
pushMatrix();
translate(x, y);
rotate(r);
image(im2, 0, 0, w, w);
popMatrix();
}
}
}
class Sun { // creates the class
int xpos;
Sun() { //The constructor of the class
}
void display() {
if (season==1) {
fill(255, 255, 0);
ellipse(xpos, height/4, 100, 100);
}
}
void update() {
xpos=xpos+2;
}
}
class Boid {
PVector position;
PVector velocity;
PVector acceleration;
PVector ddirection = new PVector(-1,-1);
float r;
float maxforce; // Maximum steering force
float maxspeed=20; // Maximum speed
int currentFrame = 0;
Boid(float x, float y) {
acceleration = new PVector(0, 0);
// This is a new PVector method not yet implemented in JS
// velocity = PVector.random2D();
// Leaving the code temporarily this way so that this example runs in JS
float angle = random(TWO_PI);
velocity = new PVector(cos(angle), sin(angle));
position = new PVector(x, y);
r = 2.0;
maxspeed = 2;
maxforce = 0.03;
}
void run(ArrayList<Boid> boids) {
flock(boids);
update();
render();
}
void applyForce(PVector force) {
// We could add mass here if we want A = F / M
acceleration.add(force);
}
// We accumulate a new acceleration each time based on three rules
void flock(ArrayList<Boid> boids) {
PVector sep = separate(boids); // Separation
PVector ali = align(boids); // Alignment
PVector coh = cohesion(boids); // Cohesion
// Arbitrarily weight these forces
sep.mult(1.5);
ali.mult(1.0);
coh.mult(1.0);
// Add the force vectors to acceleration
applyForce(sep);
applyForce(ali);
applyForce(coh);
}
// Method to update position
void update() {
// Update velocity
velocity.add(acceleration);
// Limit speed
velocity.limit(maxspeed);
position.add(velocity);
//position.add(ddirection);
// Reset accelertion to 0 each cycle
acceleration.mult(0);
}
// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
PVector seek(PVector target) {
PVector desired = PVector.sub(target, position); // A vector pointing from the position to the target
// Scale to maximum speed
desired.normalize();
desired.mult(maxspeed);
// Above two lines of code below could be condensed with new PVector setMag() method
// Not using this method until Processing.js catches up
// desired.setMag(maxspeed);
// Steering = Desired minus Velocity
PVector steer = PVector.sub(desired, velocity);
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
void render() {
// Draw a triangle rotated in the direction of velocity
float theta = velocity.heading2D() + radians(90);
// heading2D() above is now heading() but leaving old syntax until Processing.js catches up
fill(200, 100);
stroke(255);
pushMatrix();
translate(position.x, position.y);
rotate(theta);
currentFrame = (currentFrame+1) % numFrames; // Use % to cycle through frames
rotate(PI);
image(images[(currentFrame) % numFrames], 10, 10, 70, 70);
popMatrix();
}
// Separation
// Method checks for nearby boids and steers away
PVector separate (ArrayList<Boid> boids) {
float desiredseparation = 50.0f;
PVector steer = new PVector(0, 0, 0);
int count = 0;
// For every boid in the system, check if it's too close
for (Boid other : boids) {
float d = PVector.dist(position, other.position);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
steer.div((float)count);
}
// As long as the vector is greater than 0
if (steer.mag() > 0) {
// First two lines of code below could be condensed with new PVector setMag() method
// Not using this method until Processing.js catches up
// steer.setMag(maxspeed);
// Implement Reynolds: Steering = Desired - Velocity
steer.normalize();
steer.mult(maxspeed);
steer.sub(velocity);
steer.limit(maxforce);
}
return steer;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
PVector align (ArrayList<Boid> boids) {
float neighbordist = 100;
PVector sum = new PVector(0, 0);
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(position, other.position);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.velocity);
count++;
}
}
if (count > 0) {
sum.div((float)count);
// First two lines of code below could be condensed with new PVector setMag() method
// Not using this method until Processing.js catches up
// sum.setMag(maxspeed);
// Implement Reynolds: Steering = Desired - Velocity
sum.normalize();
sum.mult(maxspeed);
PVector steer = PVector.sub(sum, velocity);
steer.limit(maxforce);
return steer;
} else {
return new PVector(0, 0);
}
}
// Cohesion
// For the average position (i.e. center) of all nearby boids, calculate steering vector towards that position
PVector cohesion (ArrayList<Boid> boids) {
float neighbordist = 100;
PVector sum = new PVector(0, 0); // Start with empty vector to accumulate all positions
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(position, other.position);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.position); // Add position
count++;
}
}
if (count > 0) {
sum.div(count);
return seek(sum); // Steer towards the position
} else {
return new PVector(0, 0);
}
}
}
class Tree { // Defines what a Tree is.
float beginx, beginy, blength, aangle;
float endX, endY;
color treeColor = color(41, 25, 3);
Tree l_branch; // This tree might have other trees inside it!
Tree r_branch; // These are the BRANCHES!
Tree (float beginX, float beginY, float bLength, float angle) { // The constructor is called when a tree is created.
beginx=beginX;
beginy=beginY;
blength=bLength;
aangle=angle;
endX = beginX + bLength*cos(angle);
endY = beginY + bLength*sin(angle);
//generate 2 new branchs
if (bLength > 5)
{
if (random(1) > 0.1) l_branch = new Tree(endX, endY, bLength*random(0.6, 0.8), angle - random(PI/15, PI/5));
if (random(1) > 0.1) r_branch = new Tree(endX, endY, bLength*random(0.6, 0.8), angle + random(PI/15, PI/5));
}
}
void move() {
endX=endX+1;
}
void draw() { // Draws this Tree.
// Draw the MAIN branch
strokeWeight(map(blength, height/4, 3, 20, 1));
stroke(treeColor);
line(beginx, beginy, endX, endY);
// Draw the OTHER branches (if they exist!).
if (l_branch != null) {
l_branch.draw();
}
if (r_branch != null) {
r_branch.draw();
}
if (r_branch ==null) {
noStroke();
if (season==1 || season==2) {
fill(60, 200, 20);
ellipse(endX, endY, 20, 20);
}
if (season==4) {
fill(153, 76, 0);
ellipse(endX, endY, 20, 20);
}
}
}
void leaves() {
if (r_branch ==null) {
ellipse(endX, endY, 20, 20);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment