Water

Version 2.1 — © 1996-2003 Christian Cohnen

Originally a Java applet (1996). The original Java applet code was transpiled to JavaScript/Canvas in 2026 so the effect can run in modern browsers without a Java plugin. The JavaScript version uses Canvas pixel manipulation with the same integer-only wave kernel.

The Water applet simulates a rippling water surface in real time. Two height fields are updated each frame using a Laplacian kernel that propagates waves across the grid. A small damping factor makes sure waves gradually fade out instead of bouncing forever. The displacement is then added to each pixel's color — bright where the surface rises, dark where it dips — which gives the typical light-refraction look you'd expect from water.

Raindrops fall at a configurable rate, ships cruise along sinusoidal paths generating bow waves, and moving the mouse over the surface creates ripples. You can lay a background image under the water or just use a solid color.

This kind of 2D wave simulation was a classic effect in the Atari ST, Amiga and PC demoscene of the 1990s. The entire core loop runs on integer shifts and additions only — no multiplications, no divisions — which was essential on the hardware of that era and still keeps things fast today.

Features

Parameters

NameTypeDescriptionDefaultRequired
colorColorSurface color when no image is set#0000FF (blue)no
imagefilenameBackground image (scaled to applet size)no
raindropsintRaindrops per 10 seconds4no
shipsintNumber of ships cruising the surface0no
linkURLLink target when applet is clickedno
FPSEnables FPS counter (presence enables it, no value needed)offno

Applet Code Example

<applet archive="Water.jar"
  code="Water.class" width="100" height="100">
  <param name="link" value="https://www.chriscohnen.de">
  <param name="FPS">
  <param name="color" value="#0000AF">
  <param name="raindrops" value="25">
</applet>

JavaScript Canvas Version

The JavaScript port uses the same Laplacian wave kernel and integer damping but renders into an HTML5 <canvas> via ImageData. Mouse interaction creates ripples just like the original applet.

<canvas id="game" width="100" height="100"></canvas>
<script>var WATER_CFG = { color: "#0000AF", raindrops: 25 };</script>
<script src="water.min.js"></script>

Parameters (WATER_CFG)

NameTypeDescriptionDefault
colorstringSurface color hex when no image"#0000FF"
imagestringID of hidden background <img> elementnull
raindropsintRaindrops per 10 seconds4
shipsintNumber of ships cruising the surface0
linkstringURL to open on clicknull

Original Applet

Originally a Java applet (1996). The original used Java's MemoryImageSource with a PixelGrabber for background image scanning. The JavaScript version uses Canvas ImageData with a Uint32Array view for equivalent pixel manipulation. The Laplacian wave kernel and integer damping (31/32 via shift) are preserved exactly from the original.