// Maze Blur 01
// David Bollinger
// http://www.davebollinger.com
// for Processing 0109 Beta
/**
Press 'p' to toggle the maze path overlay
Press 'r' to toggle the path retrace visibility
Click to advance early to next set of random parameters
*/
static int [] dxs = {1,0,-1,0};
static int [] dys = {0,-1,0,1};
Grid grid;
Vector walkers;
PImage texture;
float turnLikelihood;
float spawnLikelihood;
float mixingRatio;
int currentseed = 1;
int nextwait = 0;
boolean bHideRetrace = true;
boolean bOverlayPath = false;
void setup() {
size(300,300);
grid = new Grid(width, height, 1);
texture = loadImage("duck300.jpg");
framerate(30);
walkers = new Vector(1000);
next();
}
void draw() {
if (nextwait > 0) {
if (--nextwait <= 0) next();
else return;
}
for (int i=0, sz=walkers.size(); i0.5) ? (olddir+1)%4 : (olddir+3)%4;
}
void spawn(int x, int y, int d) {
walkers.add( new Walker(x, y, d) );
grid.occupy(x,y);
}
void spawn(int x, int y, int d, color c) {
walkers.add( new Walker(x, y, d, c) );
grid.occupy(x,y);
}
color blend(color c1, color c2, float t) {
t = min(max(t,0),1.0);
float r1 = red(c1), g1 = green(c1), b1 = blue(c1);
float r2 = red(c2), g2 = green(c2), b2 = blue(c2);
return color( r1+t*(r2-r1), g1+t*(g2-g1), b1+t*(b2-b1) );
}
class Walker {
int x, y, ox, oy, dir;
color c;
Walker(int _x, int _y, int _d) {
this(_x, _y, _d, texture.get(_x*grid.rez+grid.rez/2, _y*grid.rez+grid.rez/2) );
}
Walker(int _x, int _y, int _d, color _c) {
ox = x = _x;
oy = y = _y;
dir = _d;
c = _c;
}
void move() {
// spawn a child?
if (random(1.0) < spawnLikelihood) {
int pd = perpdir(dir);
if (grid.isEmpty(x+dxs[pd], y+dys[pd]))
spawn(x, y, pd, c);
}
// change direction at random?
boolean redir = (random(1.0) < turnLikelihood);
if (redir) dir = randdir(dir);
// calc new position, check if stuck
int newx = x + dxs[dir];
int newy = y + dys[dir];
boolean stuck = grid.isSolid(newx,newy);
// if stuck try to jump onto a prior track
if (stuck) {
dir = randdir(dir); // for next pass
if (grid.isValidCoords(newx,newy)) {
// "jump" to those coordinates
ox = x = newx;
oy = y = newy;
return;
}
} else {
if ((x!=newx) || (y!=newy)) {
// "walk" to new coordinates
ox = x;
oy = y;
x = newx;
y = newy;
grid.occupy(x,y);
}
}
}
void draw(boolean bHideRetrace, boolean bOverlayPath) {
if ((bHideRetrace) && (x==ox) && (y==oy)) return;
color newc = texture.get(x*grid.rez+grid.rez/2, y*grid.rez+grid.rez/2);
c = blend(c, newc, mixingRatio);
fill(c);
noStroke();
rect(x*grid.rez, y*grid.rez, grid.rez, grid.rez);
if (bOverlayPath) {
stroke(#ffffff);
line(ox*grid.rez+grid.rez/2, oy*grid.rez+grid.rez/2,
x*grid.rez+grid.rez/2, y*grid.rez+grid.rez/2);
}
}
}
class Grid {
static final int EMPTY = 0;
static final int SOLID = 1;
int [][] grid;
int wid, hei;
int rows, cols, rez;
int cellcount, solidcount;
Grid(int w, int h, int r) {
wid = w;
hei = h;
setRez(r);
grid = new int[hei][wid];
wipe();
}
void setRez(int r) {
rez = r;
cols = wid / rez;
rows = hei / rez;
cellcount = rows * cols;
}
void wipe() {
for (int r=0; r=0) && (r>=0) && (c=cellcount);
}
void set(int c, int r, int v) {
if (isValidCoords(c,r)) {
if ((grid[r][c]==SOLID) && (v==EMPTY)) solidcount--;
if ((grid[r][c]==EMPTY) && (v==SOLID)) solidcount++;
grid[r][c] = v;
}
}
int get(int c, int r) {
if (isValidCoords(c,r))
return grid[r][c];
else
return SOLID;
}
boolean isEmpty(int c, int r) {
return (this.get(c,r) == EMPTY);
}
boolean isSolid(int c, int r) {
return (this.get(c,r) == SOLID);
}
void occupy(int c, int r) {
this.set(c, r, SOLID);
}
}