byte R = 0, G = 1, B = 2; // array of analog pin locations byte pot[3] = {0, 1, 2}; // array of PCM output pins byte led[3] = {9, 10, 11}; // game mechanics byte normal = B0000, // twist pot clockwise to increase brightness dependHigh = B0001, // pot depends on another pot, below, being high to operate redDep = B0010, // bits for dependencies greenDep = B0100, blueDep = B1000; // the levels are specified in this array byte mechanics[15] = { normal, normal, normal, // level 0 blueDep | dependHigh, normal, normal, // level 1 normal, redDep, redDep | dependHigh, // level 2 greenDep, blueDep, normal, // level 3 blueDep, redDep | dependHigh, normal // level 4 }; // the current level int level = 0; // value tolerance (to account for minor changes in pot position) byte tolerance = 64; // value stores boolean locked[3]; byte offset[3]; int value[3]; void setup() { pinMode(led[R], OUTPUT); pinMode(led[G], OUTPUT); pinMode(led[B], OUTPUT); Serial.begin(9600); // let's play! flash(3); // set the initial offset for the pots (game should always start at dim LEDs) offset[R] = analogRead(pot[R]) >> 2; offset[G] = analogRead(pot[G]) >> 2; offset[B] = analogRead(pot[B]) >> 2; } void loop() { // let's play! fetch the value of the LED based on the game mechanics and pot position value[R] = fetch(R); value[G] = fetch(G); value[B] = fetch(B); // update the LEDs setColor(value[R], value[G], value[B]); if(won()) { level++; if (level*3 >= sizeof(mechanics)) // you win the game! there are no more levels flash(10); else { // you win this round! reset the variables and offset for the next level flash(3); offset[R] = analogRead(pot[R]) >> 2; offset[G] = analogRead(pot[G]) >> 2; offset[B] = analogRead(pot[B]) >> 2; memset(value, 0, sizeof(value)); memset(locked, false, 3); // uh oh! mix up the pot assignments for the final level if (level == 4) { pot[R] = 1; pot[G] = 0; pot[B] = 2; } } } } // cause a sequential R, G, B flash of a specified count void flash(int count) { int d = 100; if (count < 0) return; for (int i = 0; i < count; i++) { setColor(255, 0, 0); delay(d); setColor(0, 255, 0); delay(d); setColor(0, 0, 255); delay(d); setColor(0,0,0); delay(d); } } // the user has won if each LED is within the tolerance for being "on" boolean won() { int on = 255 - tolerance; return (value[R] >= on && value[G] >= on && value[B] >= on); } // fetch the value for the LED, based on the rules for the level byte fetch(byte c) { // get the raw value from the pot byte raw = analogRead(pot[c]) >> 2, m = mechanics[3 * level + c]; // only fetch a new value if the pot has changed) if (abs(raw - offset[c]) < 8) return value[c]; // does this pot depend on another being high or low? if so, wait until that pot is set correctly if (m & redDep && m & dependHigh && value[R] < 255 - tolerance) { locked[c] = true; return value[c]; } if (m & redDep && ~m & dependHigh && value[R] > tolerance) { locked[c] = true; return value[c]; } if (m & greenDep && m & dependHigh && value[G] < 255 - tolerance) { locked[c] = true; return value[c]; } if (m & greenDep && ~m & dependHigh && value[G] > tolerance) { locked[c] = true; return value[c]; } if (m & blueDep && m & dependHigh && value[B] < 255 - tolerance) { locked[c] = true; return value[c]; } if (m & blueDep && ~m & dependHigh && value[B] > tolerance) { locked[c] = true; return value[c]; } if (locked[c]) { locked[c] = false; if (raw > value[c]) offset[c] = raw - value[c]; else offset[c] = value[c] - raw; } // calculate the value based on the game mechanic // based on the equation (graphing it makes it easier to understand): // y = 255 - abs( 2*(x-offset) % 512 - 255 ) return 255 - abs((((raw - offset[c] + 512) << 1) % 512) - 255); /* below are other game mechanics ideas, included only for interest if (m & middle && m & inverse) { // 0011 middle of pot range is minimum, ends are maximum; out= abs(2*input-255) val = (abs((raw << 1) - 255) - offset[c]) % 256; } else if (m & middle) { // 0010 middle of pot range is maximum, ends are minimum; out= 255-abs(2*input-255) val = (255 - abs((raw << 1) - 255) - offset[c]) % 256; } else if (m & inverse) { // 0001 twist pot anticlockwise to increase brightness val = (255 - raw - offset[c]) % 256; } else { // 0000 twist pot clockwise to increase brightness val = (raw - offset[c]) % 256; } return val; */ } // display a color defined by an RGB triplet void setColor(byte r, byte g, byte b) { analogWrite(led[R], r); analogWrite(led[G], g); analogWrite(led[B], b); }