Commit | Line | Data |
---|---|---|
f7f0bfe5 LW |
1 | class CubeState { |
2 | public Integer index; | |
3 | public boolean alive; | |
4 | public List<Integer> neighbors; | |
5 | ||
6 | public CubeState(Integer index, boolean alive, List<Integer> neighbors) { | |
7 | this.index = index; | |
8 | this.alive = alive; | |
9 | this.neighbors = neighbors; | |
10 | } | |
11 | } | |
12 | ||
13 | class Life extends SCPattern { | |
14 | public final int TIME_BETWEEN_RUNS = 100; | |
15 | public final int MAX_DEAD_BRIGHTNESS = 40; | |
16 | private final SinLFO xPos = new SinLFO(0, model.xMax, 5000); | |
17 | private final SinLFO yPos = new SinLFO(0, model.yMax, 5000); | |
18 | ||
19 | public List<CubeState> cube_states; | |
20 | public int time_since_last_run; | |
21 | public boolean any_changes_this_run; | |
22 | ||
23 | public Life(GLucose glucose) { | |
24 | super(glucose); | |
25 | //outputCubeInfo(); | |
26 | initCubeStates(); | |
27 | time_since_last_run = 0; | |
28 | any_changes_this_run = false; | |
29 | addModulator(xPos).trigger(); | |
30 | addModulator(yPos).trigger(); | |
31 | } | |
32 | ||
33 | public void run(double deltaMs) { | |
34 | Integer i = 0; | |
35 | CubeState cube_state; | |
36 | ||
37 | time_since_last_run += deltaMs; | |
38 | ||
39 | if(time_since_last_run < TIME_BETWEEN_RUNS) { | |
40 | return; | |
41 | } | |
42 | any_changes_this_run = false; | |
43 | ||
44 | for (Cube cube : model.cubes) { | |
45 | cube_state = this.cube_states.get(i); | |
46 | ||
47 | if(shouldBeAlive(i)) { | |
48 | lightLiveCube(cube); | |
49 | } else { | |
50 | lightDeadCube(cube); | |
51 | } | |
52 | i++; | |
53 | } | |
54 | ||
55 | if(!any_changes_this_run) { | |
56 | randomizeCubeStates(); | |
57 | } | |
58 | ||
59 | time_since_last_run = 0; | |
60 | } | |
61 | ||
62 | public void outputCubeInfo() { | |
63 | int i = 0; | |
64 | for (Cube c : model.cubes) { | |
65 | print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n"); | |
66 | ++i; | |
67 | } | |
68 | print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n"); | |
69 | print("Edgewidth: " + Cube.EDGE_WIDTH + "\n"); | |
70 | print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n"); | |
71 | } | |
72 | ||
73 | private void initCubeStates() { | |
74 | List<Integer> neighbors; | |
75 | boolean alive = false; | |
76 | CubeState cube_state; | |
77 | this.cube_states = new LinkedList<CubeState>(); | |
78 | Integer i = 0; | |
79 | ||
80 | for (Cube c : model.cubes) { | |
81 | neighbors = findCubeNeighbors(c, i); | |
82 | alive = (i % 6 == 0); | |
83 | // alive = true; | |
84 | cube_state = new CubeState(i, alive, neighbors); | |
85 | this.cube_states.add(cube_state); | |
86 | ++i; | |
87 | } | |
88 | } | |
89 | ||
90 | private void randomizeCubeStates() { | |
91 | for (CubeState cube_state: this.cube_states) { | |
92 | if( (cube_state.index % 2 == 0) == cube_state.alive) { | |
93 | cube_state.alive = !cube_state.alive; | |
94 | } | |
95 | } | |
96 | } | |
97 | ||
98 | public List<Integer> findCubeNeighbors(Cube cube, Integer index) { | |
99 | List<Integer> neighbors = new LinkedList<Integer>(); | |
100 | Integer i = 0; | |
101 | ||
102 | for (Cube c : model.cubes) { | |
103 | if(index == i) { | |
104 | i++; | |
105 | continue; | |
106 | } | |
107 | ||
108 | if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) { | |
109 | neighbors.add(i); | |
110 | } | |
111 | ||
112 | i++; | |
113 | } | |
114 | ||
115 | return neighbors; | |
116 | } | |
117 | ||
118 | public boolean shouldBeAlive(Integer index) { | |
119 | CubeState cube_state = this.cube_states.get(index); | |
120 | Integer alive_neighbor_count = countLiveNeighbors(cube_state); | |
121 | ||
122 | boolean before_alive = cube_state.alive; | |
123 | ||
124 | if(cube_state.alive) { | |
125 | if(alive_neighbor_count < 2 || alive_neighbor_count > 3) { | |
126 | cube_state.alive = false; | |
127 | } else { | |
128 | cube_state.alive = true; | |
129 | } | |
130 | ||
131 | } else { | |
132 | if(alive_neighbor_count == 3) { | |
133 | cube_state.alive = true; | |
134 | } else { | |
135 | cube_state.alive = false; | |
136 | } | |
137 | } | |
138 | ||
139 | this.cube_states.set(index, cube_state); | |
140 | ||
141 | if(before_alive != cube_state.alive) { | |
142 | any_changes_this_run = true; | |
143 | } | |
144 | return cube_state.alive; | |
145 | } | |
146 | ||
147 | public Integer countLiveNeighbors(CubeState cube_state) { | |
148 | Integer count = 0; | |
149 | CubeState neighbor_cube_state; | |
150 | ||
151 | for(Integer neighbor_index: cube_state.neighbors) { | |
152 | neighbor_cube_state = this.cube_states.get(neighbor_index); | |
153 | if(neighbor_cube_state.alive) { | |
154 | count++; | |
155 | } | |
156 | } | |
157 | ||
158 | return count; | |
159 | } | |
160 | ||
161 | public void lightLiveCube(Cube cube) { | |
162 | for (LXPoint p : cube.points) { | |
163 | float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); | |
164 | float bv = max(0, 100 - abs(p.y - yPos.getValuef())); | |
165 | colors[p.index] = lx.hsb( | |
166 | hv, | |
167 | 100, | |
168 | //bv | |
169 | 75 | |
170 | ); | |
171 | } | |
172 | } | |
173 | ||
174 | public void lightDeadCube(Cube cube) { | |
175 | for (LXPoint p : cube.points) { | |
176 | float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); | |
177 | float bv = max(0, MAX_DEAD_BRIGHTNESS - abs(p.y - yPos.getValuef())); | |
178 | ||
179 | colors[p.index] = lx.hsb( | |
180 | hv, | |
181 | 100, | |
182 | //bv | |
183 | 10 | |
184 | ); | |
185 | } | |
186 | } | |
187 | ||
188 | } |