Skip to content

Instantly share code, notes, and snippets.

@travisofthenorth
Last active March 29, 2016 01:10
Show Gist options
  • Save travisofthenorth/dfd10ee6abba0f0c1b93 to your computer and use it in GitHub Desktop.
Save travisofthenorth/dfd10ee6abba0f0c1b93 to your computer and use it in GitHub Desktop.
Grayscale ripple sketch
/**
* Original original code (Java) by Neil Wallis
* @link http://www.neilwallis.com/java/water.html
*
* Original JS code by Sergey Chikuyonok ([email protected])
* http://chikuyonok.ru
*/
(function(){
var canvas = document.getElementById('c'),
/** @type {CanvasRenderingContext2D} */
ctx = canvas.getContext('2d'),
delay = 30,
riprad = 3,
ripplemap = [],
last_map = [],
ripple,
line_width = 20,
step = line_width * 2;
function reset() {
width = window.innerWidth,
height = window.innerHeight,
half_width = width >> 1,
half_height = height >> 1,
size = width * (height + 2) * 2,
oldind = width,
newind = width * (height + 3),
ripplemap = [],
last_map = [],
disturbances = [],
count = height / line_width;
canvas.width = width;
canvas.height = height;
with (ctx) {
fillStyle = '#fff';
fillRect(0, 0, width, height);
}
ripple = ctx.getImageData(0, 0, width, height);
for (var i = 0; i < size; i++) {
last_map[i] = ripplemap[i] = 0;
}
}
reset();
window.addEventListener('resize', function(event){
reset();
});
/**
* Main loop
*/
function run() {
newframe();
ctx.putImageData(ripple, 0, 0);
}
/**
* Disturb water at specified point
*/
function disturb(dx, dy) {
dx <<= 0;
dy <<= 0;
disturbances.push({
x: dx,
y: dy,
energy: 512,
lastUpdate: 0,
update: function() {
if (this.lastUpdate == 0) {
for (var j = this.y - riprad; j < this.y + riprad; j++) {
for (var k = this.x - riprad; k < this.x + riprad; k++) {
ripplemap[oldind + (j * width) + k] += this.energy;
}
}
this.lastUpdate = 4;
this.energy >>= 1;
}
this.lastUpdate -= 1;
}
});
for (var i = disturbances.length - 1; i >= 0; i--) {
disturbance = disturbances[i];
disturbance.update();
if (disturbance.energy == 0) {
disturbances.splice(i, 1);
}
}
}
/**
* Generates new ripples
*/
function newframe() {
var a, b, data, cur_pixel, new_pixel, old_data;
var t = oldind; oldind = newind; newind = t;
var i = 0;
// create local copies of variables to decrease
// scope lookup time in Firefox
var _width = width,
_height = height,
_ripplemap = ripplemap,
_last_map = last_map,
_rd = ripple.data,
_half_width = half_width,
_half_height = half_height;
for (var y = 0; y < _height; y++) {
for (var x = 0; x < _width; x++) {
var _newind = newind + i, _mapind = oldind + i;
data = (
_ripplemap[_mapind - _width] +
_ripplemap[_mapind + _width] +
_ripplemap[_mapind - 1] +
_ripplemap[_mapind + 1]) >> 1;
data -= _ripplemap[_newind];
data -= data >> 5;
_ripplemap[_newind] = data;
//where data=0 then still, where data>0 then wave
data = 1024 - data;
old_data = _last_map[i];
_last_map[i] = data;
if (old_data != data) {
cur_pixel = i * 4;
var newcolor = 273 - data / 20;
_rd[cur_pixel] = _rd[cur_pixel + 1] = _rd[cur_pixel + 2] = newcolor;
}
++i;
}
}
}
setInterval(run, delay);
// generate random ripples
var rnd = Math.random;
setInterval(function() {
disturb(rnd() * width, rnd() * height);
}, 200);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment