Couple of questions about lights, snow and rain

Working on a project and I have a few questions before it’s complete. First, on the third stage of my code it is snowing, but when I went to go use the same code I made for rain on my fourth stage the rain is not moving. (Also, is there a way to simplify the rain and snow function to make random circles?) Third question is I’m trying to make the windows slowly change color but when I use random in fill() it was changing too fast so I slowed down the frame rate but that caused the whole code to slow down, is there any way to slow down the changing lights without slowing down the rest of the code? Thanks!

//variables
float time=0;//for wave animation
float[]a=new float[2000];//star posx array
int stage;//season stages
float car;//car
float circleX;
float circleXr;
float snow;//snow
float rain;//rain
//float window;//windows
PImage start;
wall[]walls;//windows


void setup(){
  size(1000,700);
  start=loadImage("start.jpg");
  circleX=0;
  snow=1;
  
//windows setup
walls=new wall[71];//creates an array(list) for the windows array starts at 0
walls[0]=new wall(470,300,20,20);
walls[1]=new wall(510,300,20,20);
walls[2]=new wall(470,340,20,20);
walls[3]=new wall(510,340,20,20);
walls[4]=new wall(470,380,20,20);
walls[5]=new wall(510,380,20,20);
walls[6]=new wall(470,420,20,20);
walls[7]=new wall(510,420,20,20);
walls[8]=new wall(470,460,20,20);
walls[9]=new wall(510,460,20,20);
walls[10]=new wall(470,500,20,20);
walls[11]=new wall(510,500,20,20);
walls[12]=new wall(470,540,20,20);
walls[13]=new wall(510,540,20,20);
walls[14]=new wall(770,300,20,20);
walls[15]=new wall(810,300,20,20);
walls[16]=new wall(770,340,20,20);
walls[17]=new wall(810,340,20,20);
walls[18]=new wall(770,380,20,20);
walls[19]=new wall(810,380,20,20);
walls[20]=new wall(770,420,20,20);
walls[21]=new wall(810,420,20,20);
walls[22]=new wall(770,460,20,20);
walls[23]=new wall(810,460,20,20);
walls[24]=new wall(770,500,20,20);
walls[25]=new wall(810,500,20,20);
walls[26]=new wall(770,540,20,20);
walls[27]=new wall(810,540,20,20);
walls[28]=new wall(870,340,20,20);
walls[29]=new wall(915,380,20,20);
walls[30]=new wall(960,380,20,20);
walls[31]=new wall(870,380,20,20);
walls[32]=new wall(915,420,20,20);
walls[33]=new wall(960,420,20,20);
walls[34]=new wall(870,420,20,20);
walls[35]=new wall(915,460,20,20);
walls[36]=new wall(960,460,20,20);
walls[37]=new wall(870,460,20,20);
walls[38]=new wall(915,340,20,20);
walls[39]=new wall(960,340,20,20);
walls[40]=new wall(960,500,20,20);
walls[41]=new wall(915,500,20,20);
walls[42]=new wall(870,500,20,20);
walls[43]=new wall(960,540,20,20);
walls[44]=new wall(915,540,20,20);
walls[45]=new wall(870,540,20,20);
walls[46]=new wall(15,300,20,20);
walls[47]=new wall(55,340,20,20);
walls[48]=new wall(15,340,20,20);
walls[49]=new wall(55,380,20,20);
walls[50]=new wall(15,380,20,20);
walls[51]=new wall(55,420,20,20);
walls[52]=new wall(15,420,20,20);
walls[53]=new wall(55,460,20,20);
walls[54]=new wall(15,460,20,20);
walls[55]=new wall(55,500,20,20);
walls[56]=new wall(15,500,20,20);
walls[57]=new wall(55,540,20,20);
walls[58]=new wall(15,540,20,20);
walls[59]=new wall(55,340,20,20);
walls[60]=new wall(55,300,20,20);
walls[61]=new wall(110,370,20,20);
walls[62]=new wall(155,370,20,20);
walls[63]=new wall(110,410,20,20);
walls[64]=new wall(155,410,20,20);
walls[65]=new wall(110,450,20,20);
walls[66]=new wall(155,450,20,20);
walls[67]=new wall(110,490,20,20);
walls[68]=new wall(155,490,20,20);
walls[69]=new wall(110,530,20,20);
walls[70]=new wall(155,530,20,20);

snow();
rain();
draw_windows();
make_stars();
}


void draw() {
  //stage 1=night time
  if (keyPressed){
    if (key=='1'){
      stage=1;
    }}
  if(stage==1);{
  background(43,47,119);
  noStroke();
  moon();//moon goes first to see stars on the cutout
  draw_stars();
  building();
  draw_windows();//windows not walls (fix name of class)
  car();
  bridge(); 
  draw_wave();//last so it is over bottom of buildings
  

//if key 2 is pressed stage=2
if (keyPressed){
    if (key=='2'){
      stage=2;
    }}
if (keyPressed){
    if (key=='3'){
      stage=3;
    }}
if (keyPressed){
    if (key=='4'){
      stage=4;
    }}
  if (keyPressed){
    if (key=='5'){
      stage=5;
    }}}

//stage 2=day time
if (stage==2){
background(116,mouseY,mouseX);
noStroke();
  draw_sun();
  building_stage2();
  draw_windows();
  car();
  bridge(); 
  draw_wave2();       
if (keyPressed){
    if (key=='3'){
      stage=3;
    }}
  if (keyPressed){
    if (key=='5'){
      stage=5;
    }}}

//stage 3=winter
if (stage==3){
  background(116,204,244);
  noStroke();
  building_stage2();
  draw_windows();
  car();
  bridge(); 
  draw_wave3();
  snow();
  if (keyPressed){
    if (key=='4'){
      stage=4;
    }}
  if (keyPressed){
    if (key=='5'){
      stage=5;
    }}}

//stage 4=rain
if (stage==4){
  background(43,47,119);
  noStroke();
  building();
  draw_windows();//windows not walls (fix name of class)
  car();
  bridge(); 
  draw_wave4();//last so it is over bottom of buildings
  rain();
  if (keyPressed){
    if (key=='5'){
      stage=5;
    }}}
    
if (stage==5){
  background(255);
  //image(start,0,0,1000,700);
  textSize(30);
  text("Instructions",380,30);
  //text("Press 1 for Night time",
}
}



void car(){
  car=car+1;
   if (car>= width+100){
    car=0;
   }
  fill(192,192,192);
  rect(car,460,30,20);
  rect(car-120,460,30,20);
  rect(car-300,460,30,20);
  
}

void moon(){
  fill(254,252,215);
  noStroke();
  ellipse(900,100,150,150);
  noStroke();
  fill(43,47,119);
  ellipse(880,90,125,125);
}

void building(){
  noStroke();
  fill(0,0,80);
  rect(450,280,100,350);//middle building
  rect(465,220,70,60);//"
  rect(479,200,40,20);//"
  rect(496,170,5,30); //"
  rect(850,320,300,300);//far right building 
  rect(750,280,100,350);//second one from the right
  rect(0,280,100,350);//far left building
  rect(100,350,100,300);//second from the left building
}
void building_stage2() {
  noStroke();
  fill(102,120,127); 
  rect(450,280,100,350);  
  rect(465,220,70,60);
  rect(479,200,40,20);
  rect(496,170,5,30); 
  rect(850,320,300,300);  
  rect(750,280,100,350);  
  rect(0,280,100,350);    
  rect(100,350,100,300);  
}


void bridge() {
  //bridge
  stroke(0);
  for (int i=0; i<1000; i=i+10) {
    line(i,440,i,480);
  }
  fill(0);
  rect(0,440,1000,10);
  rect(0,480,1000,20);
}


//
void make_stars(){
  for (int i=0; i<a.length;i++) a[i]=random(0,1700);
}

void draw_stars(){
  fill(255,255,255);
  for (int i=0;i<a.length; i++) ellipse(a[i],i*0.4,2,2);
}

void draw_wave() {
  
  float x=0;
  stroke(0);
  while(x<width){
    line(x,520+50*noise(x/100,time),x,height);
    x=x+1;
  }
  time=time+0.01;
}

void draw_wave2(){
  float x=0;
  stroke(15,94,156);
  while(x<width){
    line(x,520+50*noise(x/100,time),x,height);
    x=x+1;
  }
  time=time+0.01;
}

void draw_wave3(){
  fill(255);
  noStroke();
  rect(0,530,1000,1000);
  }
  
void draw_wave4(){
  float x=0;
  stroke(0);
  while(x<width){
    line(x,450+200*noise(x/100,time),x,height);
    x=x+1;
  }
  time=time+0.01;
}
  


void draw_sun(){
  noStroke();
  fill(805,140,0);
  ellipse(850,110,100,100);
  fill(805,165,0,90);
  ellipse(850,110,170,170);
  fill(805,165,0,60);
  ellipse(850,110,200,200);
  
}


class wall {
float x;
float y;
float w;
float h;
wall(float x1,float y1,float w1,float h1){
x = x1;
y = y1;
w = w1;
h = h1;
}


//draws the windows
void draw(){
  
  
  noStroke();
  //frameRate(2);
  fill(255,255,224);
  
  rect(x,y,w,h);
  
}
}

void draw_windows(){
  //windows
for (int i=0;i<walls.length;i++){
  walls[i].draw();
}
}

void snow(){
  circleX=circleX+snow;
  if (circleX>=width){
    circleX=0;
  }
fill(255,150);
ellipse(10,circleX,10,10);
ellipse(50,circleX+20,10,10);
ellipse(80,circleX,5,5);
ellipse(110,circleX+100,5,5);
ellipse(140,circleX+150,10,10);
ellipse(180,circleX-200,10,10);
ellipse(200,circleX-150,5,5);
ellipse(240,circleX-50,5,5);
ellipse(240,circleX,10,10);
ellipse(300,circleX+20,5,5);
ellipse(440,circleX,10,10);
ellipse(440,circleX,10,10);
ellipse(550,circleX+100,10,10);
ellipse(530,circleX-250,10,10);
ellipse(530,circleX-200,5,5);
ellipse(580,circleX-300,5,5);
ellipse(300,circleX-400,5,5);
ellipse(140,circleX-350,5,5);
ellipse(400,circleX-300,5,5);
ellipse(550,circleX,5,5);
ellipse(800,circleX,5,5);
ellipse(600,circleX,5,5);
ellipse(700,circleX,5,5);
ellipse(900,circleX,5,5);
ellipse(70,circleX-300,5,5);
ellipse(800,circleX-400,5,5);
ellipse(940,circleX-350,5,5);
ellipse(600,circleX-300,5,5);
ellipse(600,circleX,10,10);
ellipse(700,circleX+20,10,10);
ellipse(600,circleX,5,5);
ellipse(710,circleX+100,5,5);
ellipse(840,circleX+150,10,10);
ellipse(880,circleX-200,10,10);
ellipse(600,circleX-150,5,5);
ellipse(740,circleX-50,5,5);
ellipse(640,circleX,10,10);
ellipse(810,circleX+20,5,5);
ellipse(640,circleX,10,10);
ellipse(740,circleX,10,10);
ellipse(550,circleX+100,10,10);
ellipse(630,circleX-250,10,10);
}

void rain(){
  circleX=circleX+rain;
  if (circleX>=width){
    circleX=0;
  }
fill(255,150);
ellipse(10,circleX,10,10);
ellipse(50,circleX+20,10,10);
ellipse(80,circleX,5,5);
ellipse(110,circleX+100,5,5);
ellipse(140,circleX+150,10,10);
ellipse(180,circleX-200,10,10);
ellipse(200,circleX-150,5,5);
ellipse(240,circleX-50,5,5);
ellipse(240,circleX,10,10);
ellipse(300,circleX+20,5,5);
ellipse(440,circleX,10,10);
ellipse(440,circleX,10,10);
ellipse(550,circleX+100,10,10);
ellipse(530,circleX-250,10,10);
ellipse(530,circleX-200,5,5);
ellipse(580,circleX-300,5,5);
ellipse(300,circleX-400,5,5);
ellipse(140,circleX-350,5,5);
ellipse(400,circleX-300,5,5);
ellipse(550,circleX,5,5);
ellipse(800,circleX,5,5);
ellipse(600,circleX,5,5);
ellipse(700,circleX,5,5);
ellipse(900,circleX,5,5);
ellipse(70,circleX-300,5,5);
ellipse(800,circleX-400,5,5);
ellipse(940,circleX-350,5,5);
ellipse(600,circleX-300,5,5);
ellipse(600,circleX,10,10);
ellipse(700,circleX+20,10,10);
ellipse(600,circleX,5,5);
ellipse(710,circleX+100,5,5);
ellipse(840,circleX+150,10,10);
ellipse(880,circleX-200,10,10);
ellipse(600,circleX-150,5,5);
ellipse(740,circleX-50,5,5);
ellipse(640,circleX,10,10);
ellipse(810,circleX+20,5,5);
ellipse(640,circleX,10,10);
ellipse(740,circleX,10,10);
ellipse(550,circleX+100,10,10);
ellipse(630,circleX-250,10,10);
}

Hi,

To answer your first question, the rain is not moving because you never initialize your rain variable. Just set it to 1 (for example) in setup() and it will move.


For you second question, yes there are solutions. for example you can:

  • Use an array to record all the positions and draw the ellipses at those positions
  • Use object oriented programming to keep track of all your raindrops or snowflakes

In both cases, you can use the random() function to initialize the objects randomly.


To slowly change the color, you can use the lerpColor() function: https://processing.org/reference/lerpColor_.html

The lowest the amount is, the slowest the color will change.

1 Like

You can check the example sketch below to see how you can handle your rain (or your snow flakes) with object oriented programming:

ArrayList<RainDrop> drops; // drops = Variable to keep track of all the raindrops : it is a list (it's like an array but you can change its length when you want)

void setup() {
  size(1280, 720);
  drops = new ArrayList<RainDrop>(); // Initializing the list : there is nothing in it right now
}

void draw() {
  background (20); // Clearing the screen

  if (random(1) > .5) { // Adding a new rain drop 50% of the time = about every 2 frames
    drops.add(new RainDrop()); 
  }

  if (!drops.isEmpty()) { // We need to check that the list is not empty before manipulating it
    for (int i = drops.size() - 1; i >= 0; i--) { // We go trhough all the elements in the lists. We go backward because if we remove an element of the list, it messes up the indexes in the other direction
      drops.get(i).move(); // We move the drop i
      if (drops.get(i).isOutsideScreen()) { // If the drop i is below the screen
        drops.remove(i); // We remove it because we can't see it anymore so it would be useless to perform computation on it (and over time it will have a huge impact on the performance)
      } else {
        drops.get(i).show(); // Otherwise (if it is still on screen) we can show it
      }
    }
  }
}


// This is the template of a rain drop
class RainDrop {
  private int size; // A rain drop have a size
  float x, y, speed; // It also have an x position, a y postiion and a speed 

  // This is called the constructor, it is here to initialize all the variables of the rain drop
  RainDrop() {
    x = random(width); // We make its x position random (but in the screen)
    y = - 20; // It start outside the screen above it
    speed = random(10, 22); // The speed is random too 
    size = (int)random(6, 15); // the size is also random
  }

  // THis method is called when you want to move the drop down
  void move() {
    y += speed;
  }

  // Tis one is called to display it on screen
  void show() {
    fill(20, 20, 200);
    noStroke();
    ellipse(x, y, size/2, 2*size);
  }

  // This method return true if the drop is outside the screen, below it. Otherwise it is false
  boolean isOutsideScreen() {
    return y > (height + 20);
  }
}

For the color variation, please consider the following example:

color c, cInit, cFinal;
final float speed = 0.005; // Change that value between 0 and 1 to see the effect on the speed in the color change (Above 0.1 it goes too fast to be able to see it)
float amt;

void setup() {
  size(1280, 720);
  
  cInit = color(200, 20, 20); // Set the intial color
  cFinal = color(20, 20, 200); // Set the color you want to change the background to
  amt = 0; // Control the "slider" position between the 2 colors
  
  background(cInit); // At the begining the color of the background is the initial color
}


void draw() {
  amt += speed; // Move the "slider" position a bit each frame
  constrain(amt, 0, 1); // Be sure that the amt value is always between 0 and 1
  c = lerpColor(cInit, cFinal, amt); // Get a color in between the initial color and the final color based on the "slider" value (amt)
  background(c); // Set the color of the background to that new color
}

Thank you that object orientating example is a bit too complex for me, I’ll probably stick to what I have but I’m still not sure why the snow is moving but the rain is not in my code.

I told you in my first post:

1 Like

you say
snow=1;
but you forgot rain=1; in setup()

is there a way to simplify the rain and snow function to make random circles?
make a for loop in setup to fill 2 arrays with x and y position respectively using random.
In function rain() snow() make a for loop to for loop over those :

for(int i.... ){
   ellipse(xPos[i], yPos[i]...

}

for color transition look at lerpcolor in the reference
https://processing.org/reference/lerpColor_.html

use a very small value (0.001) to change the amt parameter (which is only from 0 to 1)

1 Like

apologies I think I didn’t update the page in my browser so I saw only the initial OP and not the good answers.

That’s why I answered.

Sorry.

circleX should be named circleY