class CubeState { public Integer index; public boolean alive; public List neighbors; public CubeState(Integer index, boolean alive, List neighbors) { this.index = index; this.alive = alive; this.neighbors = neighbors; } } 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); public List cube_states; public int time_since_last_run; public boolean any_changes_this_run; public Life(GLucose glucose) { super(glucose); //outputCubeInfo(); initCubeStates(); time_since_last_run = 0; any_changes_this_run = false; addModulator(xPos).trigger(); addModulator(yPos).trigger(); } public void run(double deltaMs) { Integer i = 0; CubeState cube_state; 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); if(shouldBeAlive(i)) { lightLiveCube(cube); } else { lightDeadCube(cube); } i++; } if(!any_changes_this_run) { randomizeCubeStates(); } time_since_last_run = 0; } public void outputCubeInfo() { int i = 0; for (Cube c : model.cubes) { print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n"); ++i; } print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n"); print("Edgewidth: " + Cube.EDGE_WIDTH + "\n"); print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n"); } private void initCubeStates() { List neighbors; boolean alive = false; CubeState cube_state; this.cube_states = new LinkedList(); Integer i = 0; for (Cube c : model.cubes) { neighbors = findCubeNeighbors(c, i); alive = (i % 6 == 0); // alive = true; cube_state = new CubeState(i, alive, neighbors); this.cube_states.add(cube_state); ++i; } } private void randomizeCubeStates() { for (CubeState cube_state: this.cube_states) { if( (cube_state.index % 2 == 0) == cube_state.alive) { cube_state.alive = !cube_state.alive; } } } public List findCubeNeighbors(Cube cube, Integer index) { List neighbors = new LinkedList(); 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)) { neighbors.add(i); } i++; } return neighbors; } public boolean shouldBeAlive(Integer index) { CubeState cube_state = this.cube_states.get(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; } else { cube_state.alive = true; } } else { if(alive_neighbor_count == 3) { cube_state.alive = true; } else { cube_state.alive = false; } } this.cube_states.set(index, cube_state); if(before_alive != cube_state.alive) { any_changes_this_run = true; } return cube_state.alive; } public Integer countLiveNeighbors(CubeState cube_state) { Integer count = 0; CubeState neighbor_cube_state; for(Integer neighbor_index: cube_state.neighbors) { neighbor_cube_state = this.cube_states.get(neighbor_index); if(neighbor_cube_state.alive) { count++; } } 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 ); } } }