2D Raindrops


Another small project that I made in Processing.

Here are the codes

It requires PeasyCam for camera control, ControlP5 for UI, and PBox2D as the 2D physics library.

The program itself is comprised of 5 classes:

  • sketch_dec29a: the main file of processing. It comprises of functions such as setup() or draw(), which draws parallel to OpenGL’s init() and draw() functions.
  • UserInterface: basically the class to create the GUI, it uses ControlP5 library.
  • Raindrops: which represents all the water drops. It uses the physics engine to control the speed of falling, and how the droplet reacts to barriers.
  • BezierData: is the visual representations of the curves drawn on the screen, it provides functions to draw, pick and edit each drawn bezier curve.
  • Barrier: if BezierData is the visual representation, then Barrier is the physics representations of each curve. When a water drop collide with barrier, it will use barrier’s property to calculate its bouncing direction and speed.
  • BezierDataManager: basically a convenient class to manage all the drawn bezier curves.

Here are some snippets which I think are important:


void setup() {
  Basically create a new instance of the physics engine, 
  and start listening for collisions happening 
  world = new PBox2D( this );

void draw() {
    For each time the rendering loop occurs, we need to do a time-step increment 
    for the physics engine, and also update our raindrops
    raindrops.update( 1 );


void initLiquid() {
    Create circle within the physics engine and define its property
    CircleDef circle_def   = new CircleDef();
    circle_def.radius      = world.scalarPixelsToWorld( 3 );
    circle_def.density     = 0.01f;
    circle_def.friction    = 0.01f;
    circle_def.restitution = 0.51f;

    liquid = new Body[NO_OF_PARTICLES];
    for (int i = 0; i < NO_OF_PARTICLES; ++i) {
      Create body definition representing each raindrops
      BodyDef body_def       = new BodyDef();
      body_def.position      = world.coordPixelsToWorld( random( 50, 750 ), random( -600, 0 ) );
      body_def.fixedRotation = true;

      Body body = world.createBody( body_def );

      liquid[i] = body;
      liquid[i].createShape( circle_def );

void draw() {
    Retrieve the transformed coordinate of the each droplet from 
    the physics engine and draw it onscreen
    for ( Body drop : liquid ) {
      Vec2 pos = world.getBodyPixelCoord( drop );
      point( pos.x, pos.y );

Every time before we draw the droplet, we update the velocity of each droplets, 
by dampening / slowing it down a bit
void update( float rate ) {
void dampenLiquid() {
    for ( Body b : liquid ) 
      b.setLinearVelocity( b.getLinearVelocity().mul(0.993f) );


Each bezier provides functionality to pick the control points of the curve, 
so that users can modify the curve. 
But the more important part here is that its encapsulated Barrier instance 
are used to create a body that has physical property (so that droplets can react to it)
void doneEditing() {
    barrier.makeBody( bezierPoints );


void makeBody( List vertices ) {
    Similar to Raindrops, here we create chain of edges definition, 
    set some properties to it, and then create the corresponding body 
    in the physics engine
    EdgeChainDef edges = new EdgeChainDef();

    for ( Vec2 vert : vertices ) 
      edges.addVertex( world.coordPixelsToWorld( vert ) );

    edges.setIsLoop( false );
    edges.friction = 0.05;
    edges.restitution = 0.03;

    BodyDef def = new BodyDef();
    def.position.set( 0, 0 );
    body = world.createBody( def );
    body.createShape( edges );

One thought on “2D Raindrops

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s