/* autogenerated by Processing revision 1286 on 2022-12-05 */
import processing.core.*;
import processing.data.*;
import processing.event.*;
import processing.opengl.*;

import java.util.HashMap;
import java.util.ArrayList;
import java.io.File;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

public class SnowFlakesFalling extends PApplet {

class Snowflake
{
 float CXDrift = 0;
 float MaxRandRotation;
 public float Size;
 public float StrokeWeight;
 public int numlayers;
 public float[] Angles;
 public int[] Lengths;
 public int Color;
 public int Fallspeed;
 public int PSymmetry;
 public float ArmAngleDelta;
 public int CX;
 public int CY;
 public float CRot;
 public int CLayer;
 public float ArmStartRot;
 public Snowflake()
 {
  Size = random(0.1f, 0.5f);
  numlayers = PApplet.parseInt(random(2, 12));  
  Angles = new float[numlayers];
  Lengths = new int[numlayers];
  for(int i = 0; i < numlayers; i++)
  {
    Angles[i] = random(100, 1900) / 1000 * PI;
    Lengths[i] = PApplet.parseInt(random(10, 100));
  }
  Color = min(PApplet.parseInt(random(30, 127)) * numlayers, 255);
  StrokeWeight = PApplet.parseInt(random(0, 2)) * Size;
  Fallspeed = PApplet.parseInt(random(1, 5));
  PSymmetry = PApplet.parseInt(random(6, 12));
  ArmAngleDelta = 2 * PI / PSymmetry;
  CXDrift = random(-2.0f, 2.0f);
  CX = PApplet.parseInt(random(ScreenWidth));
  CY = 0;
  CRot = 0;
  CLayer = 0;
  ArmStartRot = 0;
  MaxRandRotation = random(-1.0f, 1.0f) / 20;
 }
 public void MoveSelf()
 {
  CXDrift += random(-1.0f, 1.0f) / 20;
  CX += CXDrift + Wind; 
  CY += Fallspeed;
  Angles[0] += MaxRandRotation;
  if(CY > ScreenHeight + 10)
  {
   CY = -10; 
  }
  if(CX > ScreenWidth)
  {
   CX = -10; 
  }
  if(CX < -10)
  {
   CX = ScreenWidth + 10; 
  }
 }
 public void DrawSnowFlake(Point Startp, float StartAn)
 {
   for(int i = 0; i < PSymmetry; i++)
   {
     MakeArm(Startp, StartAn, 0);
     StartAn += ArmAngleDelta;
   }
 }
  public void MakeArm(Point Lastp, float LastAn, int Layernum)
{
  stroke(Color); 
  strokeWeight(StrokeWeight);
  if(Layernum >= numlayers)
  {
    return;
  }
  float NewAn = LastAn + Angles[Layernum];
  Point Newp = new Point(PApplet.parseInt(Lastp.X + cos(NewAn) * Lengths[Layernum] * Size), PApplet.parseInt(Lastp.Y + sin(NewAn) * Lengths[Layernum] * Size));
  line(Lastp.X, Lastp.Y, Newp.X, Newp.Y);
  Layernum++;
  this.MakeArm(Newp, NewAn, Layernum);
}
}

class Point
{
 public int X;
 public int Y;
 public Point(int xargs, int yargs)
 {
   X = xargs;
   Y = yargs;
 }
}
public int Tick = 0;
public float Wind = 0;
public float WindDelta = 0;
public int ScreenWidth = 1960;
public int ScreenHeight = 1080;
public int FlakeNum = 20;
public boolean Stopped = false;
public int MaxSnowFlakeNum = 400;
public Snowflake[] Snowflakes;

 public void setup()          /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
   frameRate(60);
   background(0);
}

 public void settings()
{
  size(ScreenWidth, ScreenHeight);
  Snowflakes = InitializeSnow(FlakeNum);
}
 public Snowflake[] InitializeSnow(int FlakeNum)
{
  Snowflake[] newSnowflakes = new Snowflake[MaxSnowFlakeNum];
  for(int i = 0; i < FlakeNum; i++)
  {
    newSnowflakes[i] = new Snowflake();
  }
  return newSnowflakes;
}
 public void draw()
{
  background(0);
  
  for (int i = 0; i < FlakeNum; i++) 
  {  
    stroke(Snowflakes[i].Color);
    Point SfC = new Point(Snowflakes[i].CX, Snowflakes[i].CY);
    //line(SfC.X, SfC.Y, 100, 100);
    
    Snowflakes[i].DrawSnowFlake(SfC, Snowflakes[i].Angles[0]);
    Snowflakes[i].MoveSelf();
  }
  if(Tick % 50 == 0)
  {
    if(WindDelta > 1)
    {
      WindDelta = random(-1.0f, 0.0f)/100;
    }
    else
    {
      WindDelta = random(0.0f, 1.0f)/100;
    }
  }
  Wind += WindDelta;
  if(FlakeNum + 1 < MaxSnowFlakeNum)
  {
    Snowflakes[FlakeNum] = new Snowflake();
    FlakeNum++;
    println(FlakeNum);
  }
  Tick++;
}


  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "SnowFlakesFalling" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}
