37 Ripple(
int id) : rippleId(
id) {
38 Serial.print(
"Instanced ripple #");
39 Serial.println(rippleId);
42 rippleState state = dead;
52 void start(
byte n,
byte d,
unsigned long c,
float s,
unsigned long l,
byte b) {
67 Serial.print(
"Ripple ");
68 Serial.print(rippleId);
69 Serial.print(
" starting at node ");
70 Serial.print(position[0]);
71 Serial.print(
" direction ");
72 Serial.println(position[1]);
75 void advance(
byte ledColors[40][14][3]) {
76 unsigned long age = millis() - birthday;
81 pressure += fmap(
float(age), 0.0,
float(lifespan), speed, 0.0);
84 if (pressure < 1 && (state == travelingUpwards || state == travelingDownwards)) {
86 renderLed(ledColors, age);
89 while (pressure >= 1) {
90#ifdef DEBUG_ADVANCEMENT
91 Serial.print(
"Ripple ");
92 Serial.print(rippleId);
93 Serial.println(
" advancing:");
102#ifdef DEBUG_ADVANCEMENT
103 Serial.print(
" Picking direction out of node ");
104 Serial.print(position[0]);
105 Serial.print(
" with agr. ");
106 Serial.println(behavior);
109 int newDirection = -1;
111 int sharpLeft = (position[1] + 1) % 6;
112 int wideLeft = (position[1] + 2) % 6;
113 int forward = (position[1] + 3) % 6;
114 int wideRight = (position[1] + 4) % 6;
115 int sharpRight = (position[1] + 5) % 6;
120 byte anger = behavior;
122 while (newDirection < 0) {
124 int forwardConnection = nodeConnections[position[0]][forward];
126 if (forwardConnection < 0) {
128#ifdef DEBUG_ADVANCEMENT
129 Serial.println(
" Can't go straight - picking more agr. path");
134#ifdef DEBUG_ADVANCEMENT
135 Serial.println(
" Going forward");
137 newDirection = forward;
142 int leftConnection = nodeConnections[position[0]][wideLeft];
143 int rightConnection = nodeConnections[position[0]][wideRight];
145 if (leftConnection >= 0 && rightConnection >= 0) {
146#ifdef DEBUG_ADVANCEMENT
147 Serial.println(
" Turning left or right at random");
149 newDirection = random(2) ? wideLeft : wideRight;
151 else if (leftConnection >= 0) {
152#ifdef DEBUG_ADVANCEMENT
153 Serial.println(
" Can only turn left");
155 newDirection = wideLeft;
157 else if (rightConnection >= 0) {
158#ifdef DEBUG_ADVANCEMENT
159 Serial.println(
" Can only turn right");
161 newDirection = wideRight;
164#ifdef DEBUG_ADVANCEMENT
165 Serial.println(
" Can't make wide turn - picking more agr. path");
172 int leftConnection = nodeConnections[position[0]][sharpLeft];
173 int rightConnection = nodeConnections[position[0]][sharpRight];
175 if (leftConnection >= 0 && rightConnection >= 0) {
176#ifdef DEBUG_ADVANCEMENT
177 Serial.println(
" Turning left or right at random");
179 newDirection = random(2) ? sharpLeft : sharpRight;
181 else if (leftConnection >= 0) {
182#ifdef DEBUG_ADVANCEMENT
183 Serial.println(
" Can only turn left");
185 newDirection = sharpLeft;
187 else if (rightConnection >= 0) {
188#ifdef DEBUG_ADVANCEMENT
189 Serial.println(
" Can only turn right");
191 newDirection = sharpRight;
194#ifdef DEBUG_ADVANCEMENT
195 Serial.println(
" Can't make tight turn - picking less agr. path");
206 else if (behavior == alwaysTurnsRight) {
207 for (
int i = 1; i < 6; i++) {
208 int possibleDirection = (position[1] + i) % 6;
210 if (nodeConnections[position[0]][possibleDirection] >= 0) {
211 newDirection = possibleDirection;
216#ifdef DEBUG_ADVANCEMENT
217 Serial.println(
" Turning as rightward as possible");
220 else if (behavior == alwaysTurnsLeft) {
221 for (
int i = 5; i >= 1; i--) {
222 int possibleDirection = (position[1] + i) % 6;
224 if (nodeConnections[position[0]][possibleDirection] >= 0) {
225 newDirection = possibleDirection;
230#ifdef DEBUG_ADVANCEMENT
231 Serial.println(
" Turning as leftward as possible");
235#ifdef DEBUG_ADVANCEMENT
236 Serial.print(
" Leaving node ");
237 Serial.print(position[0]);
238 Serial.print(
" in direction ");
239 Serial.println(newDirection);
242 position[1] = newDirection;
245 position[0] = nodeConnections[position[0]][position[1]];
247#ifdef DEBUG_ADVANCEMENT
248 Serial.print(
" and entering segment ");
249 Serial.println(position[0]);
252 if (position[1] == 5 || position[1] == 0 || position[1] == 1) {
253#ifdef DEBUG_ADVANCEMENT
254 Serial.println(
" (starting at bottom)");
256 state = travelingUpwards;
260#ifdef DEBUG_ADVANCEMENT
261 Serial.println(
" (starting at top)");
263 state = travelingDownwards;
269 case travelingUpwards: {
272 if (position[1] >= 14) {
274#ifdef DEBUG_ADVANCEMENT
275 Serial.print(
" Reached top of seg. ");
276 Serial.println(position[0]);
279 int segment = position[0];
280 position[0] = segmentConnections[position[0]][0];
281 for (
int i = 0; i < 6; i++) {
284 int incomingConnection = nodeConnections[position[0]][i];
285 if (incomingConnection == segment)
288#ifdef DEBUG_ADVANCEMENT
289 Serial.print(
" Entering node ");
290 Serial.print(position[0]);
291 Serial.print(
" from direction ");
292 Serial.println(position[1]);
297#ifdef DEBUG_ADVANCEMENT
298 Serial.print(
" Moved up to seg. ");
299 Serial.print(position[0]);
300 Serial.print(
" LED ");
301 Serial.println(position[1]);
307 case travelingDownwards: {
309 if (position[1] < 0) {
311#ifdef DEBUG_ADVANCEMENT
312 Serial.print(
" Reached bottom of seg. ");
313 Serial.println(position[0]);
316 int segment = position[0];
317 position[0] = segmentConnections[position[0]][1];
318 for (
int i = 0; i < 6; i++) {
321 int incomingConnection = nodeConnections[position[0]][i];
322 if (incomingConnection == segment)
325#ifdef DEBUG_ADVANCEMENT
326 Serial.print(
" Entering node ");
327 Serial.print(position[0]);
328 Serial.print(
" from direction ");
329 Serial.println(position[1]);
334#ifdef DEBUG_ADVANCEMENT
335 Serial.print(
" Moved down to seg. ");
336 Serial.print(position[0]);
337 Serial.print(
" LED ");
338 Serial.println(position[1]);
350 if (state == travelingUpwards || state == travelingDownwards) {
352 renderLed(ledColors, age);
356#ifdef DEBUG_ADVANCEMENT
357 Serial.print(
" Age is now ");
360 Serial.println(lifespan);
363 if (lifespan && age >= lifespan) {
365#ifdef DEBUG_ADVANCEMENT
366 Serial.println(
" Lifespan is up! Ripple is dead.");
369 position[0] = position[1] = pressure = age = 0;
375 unsigned long lifespan;
384 bool justStarted =
false;
387 unsigned long birthday;
389 static byte rippleCount;
392 void renderLed(
byte ledColors[40][14][3],
unsigned long age) {
393 int strip = ledAssignments[position[0]][0];
394 int led = ledAssignments[position[0]][2] + position[1];
396 int red = ledColors[position[0]][position[1]][0];
397 int green = ledColors[position[0]][position[1]][1];
398 int blue = ledColors[position[0]][position[1]][2];
400 ledColors[position[0]][position[1]][0] = byte(min(255, max(0,
int(fmap(
float(age), 0.0,
float(lifespan), (color >> 8) & 0xFF, 0.0)) + red)));
401 ledColors[position[0]][position[1]][1] = byte(min(255, max(0,
int(fmap(
float(age), 0.0,
float(lifespan), (color >> 16) & 0xFF, 0.0)) + green)));
402 ledColors[position[0]][position[1]][2] = byte(min(255, max(0,
int(fmap(
float(age), 0.0,
float(lifespan), color & 0xFF, 0.0)) + blue)));
404#ifdef DEBUG_RENDERING
405 Serial.print(
"Rendering ripple position (");
406 Serial.print(position[0]);
408 Serial.print(position[1]);
409 Serial.print(
") at Strip ");
411 Serial.print(
", LED ");
413 Serial.print(
", color 0x");
414 for (
int i = 0; i < 3; i++) {
415 if (ledColors[position[0]][position[1]][i] <= 0x0F)
417 Serial.print(ledColors[position[0]][position[1]][i], HEX);