Flood of tears

Expressing grief with Processing

Danielle H
5 min readFeb 23, 2024
Gif quality is low, checkout the original in YouTube or Pixabay for nicer splashing

To skip to the code, click here.

When my brother passed away of a sudden heart attack at age 38, we were all devastated. One of the things I have done in the years following is death is create and upload a video of a song that he wrote.

I think I need someone to bleed with me on brand new sheets of silk
I think I need someone to feed me homemade cakes and milk
I think I need someone to hold me while I free myself
I think I’ll need, and then I’ll fold me and lay me on a shelf

While most of the video was the text of the song, I also used two Processing animations for the video. One was growing and flowering vines. The other, which is also the ending of the video, is the Flood of Tears (link is to Pixabay).

Tears fall and splash in a growing puddle that takes over the screen until it’s filled. Because sometimes, grief knows no bounds.

And for the last few months, grief, for completely different reasons, has been all-encompassing. So I revisited this code.

Sometimes code can give comfort.

Comfort in coding. Generated by Dall-E

Full code in GitHub

So, how does the code work?

  • Code to create a large drop — the tear.
  • Code to create small droplets when hitting the puddle: The splash
  • Code to create the flood of tears.

The tear

First, we need the shape of a tear. For this I used a custom PShape. The idea was to use a Bezier curve for the top left and top right — the “tear” — and half a circle for the bottom half of the tear:

void setup(){
size(400, 400);
background(0);
//drop PShape
drop = createShape();
drop.beginShape(); // start to draw a shape
drop.vertex(0, -50); // begin at this point x, y
//top left of drop, curving in then out
drop.bezierVertex(0, -50, 8, -25, 10, -20);
drop.bezierVertex(10, -20, 17, -10, 20, 0.3);
//bottom arc of drop
for (float a = 0; a < PI; a += 0.1) {
float r = 20;
drop.vertex(r*cos(a), r*sin(a));
}
//top right of drop, curving in then out
drop.bezierVertex(-20, 0.3, -17, -10, -10, -20);
drop.bezierVertex(-10, -20, -8, -25, 0, -50);
drop.endShape(CLOSE);

//PShapes are always drawn at 0,0, so need to translate to draw
pushMatrix();
translate(200, 200);
scale(0.5);
shape(drop);
popMatrix();
}

This results in the following:

Now we want a tear-y color. For that I played with blue, green and alpha:

float blue = random(280, 255);
float green = random(100, 200);
float alpha = random(150, 255);
drop.setFill(color(0, green, blue, alpha));

Now, I wanted it to drop:

//position, could use PVector instead
float x = 200;//center
float y = 10;//top

//drop
PShape drop;

//falling speed
float speed = 5;

//when to update the position - don't want it to fall too fast
long currTime = 0;
long prevTime = 0;
int interval = 50;//ms

...//here is the PShape code from before

void draw() {//draw and update
background(0);
//we want to draw all the time, and update if interval passed
currTime = millis();
//draw
pushMatrix();
translate(x, y);
scale(0.5);
shape(drop);
popMatrix();
//update if interval passed
if (currTime-prevTime > interval) {
prevTime = currTime;
y = y+speed;
}
}

And I also wanted it to shimmer, so I changed the alpha semi-randomly:

if (currTime-prevTime > interval) {
prevTime = currTime;
y = y+speed;
alpha = alpha + random(-10, +10);
alpha = constrain(alpha, 150, 255);
}

Now we need it to splash.

The splash

The splash is a few circular droplets. What is interesting about them is that they have an upward starting velocity, and then they fall with gravity. In other words, we need some basic physics.

class Droplet {
PVector pos; //position of droplet
PVector vel;//velocity of droplet
PVector gravity = new PVector(0, 10);//gravity
color c;//color of droplet

//create droplet with random velocity in splash-y direction
Droplet(PVector pos, color c) {
this.pos = pos;
this.c = c;
vel = new PVector(random(-20, 20), random(-30, -70));
}

//using given color to draw the droplet and update position and velocity.
void draw() {
fill(c);
noStroke();
circle(pos.x, pos.y, 10);
//physics:
//v = starting_velocity + gravity * time_unit
//time_unit is 1
vel.add(gravity);
pos.add(vel);
}
}

So when the Drop hits the puddle, we need to remove the drop, and create some random droplets instead.

The flood

The flood is actually simple. It’s a rectangle that starts with height 0 and grows bigger from below. As in Processing the top right corner is (0,0), we need to subtract the current height of the flood:

flood = height;//no flood

//when drop hits, subtact from flood:
flood -=10;

//draw flood
fill(0, 85, 255);
rect(0, flood, width, height - flood);

Flood of tears

I wanted it to feel like a flood, and have more and more tears over time. So I start with an `interval` of 3 seconds. After the interval, I create a drop … and make the interval shorter:

interval  = int(0.8*interval);

And that gives the “more and more tears” effect.

Full code is here:

May we all know better times.

139 days. Still waiting. #BringThemHome.

Check out my free and open source online game Space Short. If you like my stories and site, you can also buy me a coffee.

--

--

Danielle H

I started programming in LabVIEW and Matlab, and quickly expanded to include Android, Swift, Flutter, Web(PHP, HTML, Javascript), Arduino and Processing.