From 4861d6c4ade9dfa8bf3ee999b81e4d8c53f08346 Mon Sep 17 00:00:00 2001 From: Leighton Wallace Date: Sat, 23 Nov 2013 22:17:00 -0800 Subject: [PATCH] Life Refinements * Added knobs for rate, saturation, dead brightness, and randomization * Cleaned up code, commented out print statements. * Renamed shouldBeAlive to cycleOfLife. --- L8onWallace.pde | 179 +++++++++++++++++++++++++++--------------------- SugarCubes.pde | 11 ++- 2 files changed, 106 insertions(+), 84 deletions(-) diff --git a/L8onWallace.pde b/L8onWallace.pde index 031a083..80f8b8d 100644 --- a/L8onWallace.pde +++ b/L8onWallace.pde @@ -1,6 +1,9 @@ class CubeState { + // Index of cube in glucose.model.cubes public Integer index; + // Boolean which describes if cube is alive. public boolean alive; + // List of this cubes neighbors public List neighbors; public CubeState(Integer index, boolean alive, List neighbors) { @@ -10,55 +13,98 @@ class CubeState { } } -class Life extends SCPattern { - public final int TIME_BETWEEN_RUNS = 100; - public final int MAX_DEAD_BRIGHTNESS = 40; - private final SinLFO xPos = new SinLFO(0, model.xMax, 5000); - private final SinLFO yPos = new SinLFO(0, model.yMax, 5000); +class L8onLife extends SCPattern { + // Controls the rate of life algorithm ticks, in milliseconds + private BasicParameter rateParameter = new BasicParameter("RATE", 122.5, 0.0, 2000.0); + // Controls if the cubes should be randomized even if something changes. Set above 0.5 to randomize cube aliveness. + private BasicParameter randomParameter = new BasicParameter("RAND", 0.0); + // Controls the brightness of dead cubes. + private BasicParameter deadParameter = new BasicParameter("DEAD", 25.0, 0.0, 100.0); + // Controls the saturation. + private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0); + + public final double MIN_ALIVE_PROBABILITY = 0.1; + public final double MAX_ALIVE_PROBABILITY = 0.8; + + private final SinLFO xPos = new SinLFO(0, model.xMax, 3500); - public List cube_states; - public int time_since_last_run; - public boolean any_changes_this_run; + // Contains the state of all cubes by index. + private List cube_states; + // Contains the amount of time since the last cycle of life. + private int time_since_last_run; + // Boolean describing if life changes were made during the current run. + private boolean any_changes_this_run; - public Life(GLucose glucose) { + public L8onLife(GLucose glucose) { super(glucose); - outputCubeInfo(); + + //Print debug info about the cubes. + //outputCubeInfo(); + initCubeStates(); time_since_last_run = 0; any_changes_this_run = false; + + addParameter(rateParameter); + addParameter(randomParameter); + addParameter(deadParameter); + addParameter(saturationParameter); addModulator(xPos).trigger(); - addModulator(yPos).trigger(); } public void run(double deltaMs) { Integer i = 0; - CubeState cube_state; + CubeState cube_state; + any_changes_this_run = false; time_since_last_run += deltaMs; - if(time_since_last_run < TIME_BETWEEN_RUNS) { - return; - } - any_changes_this_run = false; - - for (Cube cube : model.cubes) { - cube_state = this.cube_states.get(i); + for (Cube cube : model.cubes) { + cube_state = this.cube_states.get(i); - if(shouldBeAlive(i)) { + if(shouldLightCube(cube_state)) { lightLiveCube(cube); } else { lightDeadCube(cube); - } - i++; + } + + i++; } - if(!any_changes_this_run) { + boolean should_randomize_anyway = (randomParameter.getValuef() > 0.5); + if(should_randomize_anyway || !any_changes_this_run) { randomizeCubeStates(); } - time_since_last_run = 0; + if(time_since_last_run >= rateParameter.getValuef()) { + time_since_last_run = 0; + } } + public void lightLiveCube(Cube cube) { + for (LXPoint p : cube.points) { + float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); + colors[p.index] = lx.hsb( + hv, + saturationParameter.getValuef(), + 75 + ); + } + } + + public void lightDeadCube(Cube cube) { + for (LXPoint p : cube.points) { + float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); + double dead_bright = deadParameter.getValuef() * Math.random(); + + colors[p.index] = lx.hsb( + hv, + saturationParameter.getValuef(), + dead_bright + ); + } + } + public void outputCubeInfo() { int i = 0; for (Cube c : model.cubes) { @@ -86,16 +132,14 @@ class Life extends SCPattern { } } - private void randomizeCubeStates() { - print("randomizing!\n"); - - float f = (xPos.getValuef() / model.xMax) * 10; - int mod_value = max(2, (int) f); + private void randomizeCubeStates() { + double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY); + double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random()); - for (CubeState cube_state: this.cube_states) { - if( (cube_state.index % mod_value == 0) == cube_state.alive) { - cube_state.alive = !cube_state.alive; - } + //print("Randomizing cubes! p = " + prob + "\n"); + + for (CubeState cube_state: this.cube_states) { + cube_state.alive = (Math.random() <= prob); } } @@ -104,14 +148,11 @@ class Life extends SCPattern { Integer i = 0; for (Cube c : model.cubes) { - if(index == i) { - i++; - continue; - } - - if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) { - print("Cube " + i + " is a neighbor of " + index + "\n"); - neighbors.add(i); + if(index != i) { + if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) { + //print("Cube " + i + " is a neighbor of " + index + "\n"); + neighbors.add(i); + } } i++; @@ -120,12 +161,21 @@ class Life extends SCPattern { return neighbors; } - public boolean shouldBeAlive(Integer index) { - CubeState cube_state = this.cube_states.get(index); - Integer alive_neighbor_count = countLiveNeighbors(cube_state); - + public boolean shouldLightCube(CubeState cube_state) { + // Respect rate parameter. + if(time_since_last_run < rateParameter.getValuef()) { + any_changes_this_run = true; + return cube_state.alive; + } else { + return cycleOfLife(cube_state); + } + } + + public boolean cycleOfLife(CubeState cube_state) { + Integer index = cube_state.index; + Integer alive_neighbor_count = countLiveNeighbors(cube_state); boolean before_alive = cube_state.alive; - + if(cube_state.alive) { if(alive_neighbor_count < 2 || alive_neighbor_count > 3) { cube_state.alive = false; @@ -137,15 +187,16 @@ class Life extends SCPattern { if(alive_neighbor_count == 3) { cube_state.alive = true; } else { - cube_state.alive = false; + cube_state.alive = false; } } this.cube_states.set(index, cube_state); - + if(before_alive != cube_state.alive) { - any_changes_this_run = true; + any_changes_this_run = true; } + return cube_state.alive; } @@ -161,33 +212,5 @@ class Life extends SCPattern { } return count; - } - - public void lightLiveCube(Cube cube) { - for (LXPoint p : cube.points) { - float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); - float bv = max(0, 100 - abs(p.y - yPos.getValuef())); - colors[p.index] = lx.hsb( - hv, - 100, - //bv - 75 - ); - } - } - - public void lightDeadCube(Cube cube) { - for (LXPoint p : cube.points) { - float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); - float bv = max(0, MAX_DEAD_BRIGHTNESS - abs(p.y - yPos.getValuef())); - - colors[p.index] = lx.hsb( - hv, - 100, - //bv - 10 - ); - } - } - + } } diff --git a/SugarCubes.pde b/SugarCubes.pde index d4aa68f..81bb283 100644 --- a/SugarCubes.pde +++ b/SugarCubes.pde @@ -24,8 +24,7 @@ */ LXPattern[] patterns(GLucose glucose) { - return new LXPattern[] { - + return new LXPattern[] { new SineSphere(glucose), //new CubeCurl(glucose), @@ -75,8 +74,9 @@ LXPattern[] patterns(GLucose glucose) { new JackieLines(glucose), new JackieDots(glucose), - - + // L8on + new L8onLife(glucose), + // Vincent new VSTowers(glucose), @@ -92,8 +92,7 @@ LXPattern[] patterns(GLucose glucose) { new Swim(glucose), new Balance(glucose), - // L8on - new Life(glucose), + // Ben // new Sandbox(glucose), -- 2.34.1