Winter Scene GIF
I started off by playing with the noise function, and when I was observing it, I thought the way it moved looked like a row of soldiers marching. Thus I decided to create infinite rows of noise soldiers walking towards the viewer. However, after I coded it up, I realized that what I had looked more like a waterfall, so I just created a scene by going from there instead.
During the entire process of creating this gif, I spend a lot of time worrying how I could get it to loop. Not taking risks made me feel like I did not learn as much as I could from this project. Also, I did not realize that there was a template uploaded, which could have saved me a lot of time. Thirdly, I found out that I enjoy watching my animation more when I am listening to some relaxing music, rather than being in silence, so I feel it might have been better if instead it is a music video with more contents. The combined effects made me feel serene, which I am glad for.
Thanks to Daniel Shiffman for his code of the particle system.
int square_width = 15;
color skycolor = color(40,40,40);
boolean sunrise = true;
int snowcolor = 140;
int stay = 0;
int frames = 0;
ParticleSystem ps1, ps2;
class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float lifespan;
Particle(PVector l) {
acceleration = new PVector(0,0.1);
velocity = new PVector(random(-10,10),1.0);
location = l.get();
lifespan = 255.0;
}
void run() {
update();
display();
}
// Method to update location
void update() {
velocity.add(acceleration);
location.add(velocity);
lifespan -= 1.0;
}
// Method to display
void display() {
stroke(255,200 - blue(skycolor) + 2);
fill(255, 200 - blue(skycolor) + 2);
ellipse(location.x,location.y,8,8);
}
// Is the particle still useful?
boolean isDead() {
if (lifespan < 0.0) {
return true;
} else {
return false;
}
}
}
// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles
class ParticleSystem {
ArrayList particles;
PVector origin;
ParticleSystem(PVector location) {
origin = location.get();
particles = new ArrayList();
}
void addParticle() {
particles.add(new Particle(origin));
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
}
class Row_of_Noise{
int start, end;
float row;
Row_of_Noise(int s, int e, float r)
{
start = s;
end = e;
row = r;
}
void walk_forward()
{
row *= 1.03;
if(row > height)
row = 0.1;
start = width/2-(int)row*3;
end = width/2+(int)row*3;
}
}
Row_of_Noise[] RoN;
void setup() {
size(600, 600);
stroke(0);
smooth();
noiseSeed(15251);
initialize_rows_of_noise();
ps1 = new ParticleSystem(new PVector(width/3,-50));
ps2 = new ParticleSystem(new PVector(2*width/3,-50));
}
void initialize_rows_of_noise(){
RoN = new Row_of_Noise[40];
float r = 0.1;
for(int i = 0; i < RoN.length; i++)
{
r *= 1.3;
RoN[i] = new Row_of_Noise(width/2-(int)r*2,
width/2+(int)r*2,
r);
}
}
void draw_row_of_noise(Row_of_Noise ron)
{
beginShape();
float theta = 0.0;
for(int x = ron.start; x < ron.end; x++)
{
if(x % 50 == 0)
{
endShape();
beginShape();
}
if(x % 50 < 10)
continue;
float y = noise((millis()/1000.0 + x)%50.0) *
((float)(ron.end - ron.start)/ 6.0) + ron.row;
vertex(x-5,y+300);
}
endShape();
}
void draw() {
if(53 < frames && frames < 285)
saveFrame("outputgif/myname-loop-" + nf(frames,4) + ".png");
if(blue(skycolor) > 200)
{
sunrise = false;
if(stay == 0)
stay = 50;
else
stay--;
}
if(blue(skycolor) < 10)
{
sunrise = true;
if(stay == 0)
stay = 50;
else
stay--;
}
if(stay == 0)
{
if(sunrise)
{
skycolor = color(red(skycolor)+1, green(skycolor)+2, blue(skycolor)+3);
snowcolor++;
}
else
{
skycolor = color(red(skycolor)-1, green(skycolor)-2, blue(skycolor)-3);
snowcolor--;
}
}
background(skycolor);
stroke(snowcolor);
for(int i = 0; i < width; i++)
line(i,noise(i/400.0)*100.0 + 245,i,height);
// draws the waterfall
stroke(0,100,200);
noFill();
for(int i = 0; i < RoN.length; i++)
{
draw_row_of_noise(RoN[i]);
RoN[i].walk_forward();
}
ps1.addParticle();
ps1.run();
ps2.addParticle();
ps2.run();
frames++;
}