Rapacious Sapphires
UCF GAIM Physical Computing
03 March 2026
Midi Instrument and Recorder
02 March 2026
Analog Team 23
Analog Team 23
We are Analog Team 23 and we developed a memory-based sequence game using the Circuit Playground that combines visual cues with analog and digital inputs. The game begins by flashing one of three colors, each representing a specific action the player must perform. For example, yellow corresponds to turning the potentiometer knob, while blue requires pressing a button. With each successful round, the game adds another color to the sequence, increasing the difficulty and requiring the player to remember and repeat the entire pattern in order.
If the player correctly completes the sequence, the board flashes green to indicate success and advances to the next round. If a mistake is made, such as turning the potentiometer too far, which may register as multiple inputs the board flashes red and the game resets. This highlights how sensitive analog components can be and how precise input control affects gameplay.
This project demonstrates how analog sensors and programmed feedback can be combined to create an engaging, progressively challenging interactive experience.
Code:
#include <Adafruit_CircuitPlayground.h>
//Defining playground analog inputs
const byte potPin = A2;
const byte buttonPin = A3;
// Game loop variables
int sequence[50]; // stores the pattern
int roundLength = 0; // how many steps this round
void setup() {
CircuitPlayground.begin();
pinMode(buttonPin, INPUT_PULLUP);
//Random seed so the pattern changes every time the playground boots up
randomSeed(analogRead(A1));
roundLength = 1;
sequence[0] = random(0, 3);
}
void loop() {
delay(400);
// Showing the sequence first
for (int i = 0; i < roundLength; i++) {
// Light up pixels for the current step
if (sequence[i] == 0) {
// BLUE = button
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 0, 0, 255);
}
else if (sequence[i] == 1) {
// YELLOW = pot
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 255, 255, 0);
}
else {
// WHITE = tilt
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 255, 255, 255);
}
delay(500);
CircuitPlayground.clearPixels();
delay(250);
}
// Listening for player inputs
// Setting baselines
int potStart = analogRead(potPin);
bool tiltNeedsCenter = false; // boolean to make sure that the board returns to center before tilt input can be used again (prevents multiple fires)
for (int i = 0; i < roundLength; i++) {
int expected = sequence[i];
int playerAction = -1;
// Wait until the player does ONE action
while (playerAction == -1) {
// Check for button press
if (digitalRead(buttonPin) == LOW) {
playerAction = 0;
delay(200);
}
// Check for potentiometer input
int potNow = analogRead(potPin);
if (abs(potNow - potStart) > 80) {
playerAction = 1;
potStart = potNow; // update baseline
delay(200);
}
// Check for tilt
float x = CircuitPlayground.motionX();
float tiltAmount = abs(x); // Ignores tilt direction
if (tiltAmount > 8) {
tiltAmount = 8;
}
// Mapping tilts to make the player tilt the playground farther in order to get a tilt input
int tiltLevel = map((int)(tiltAmount * 100), 0, 800, 0, 100);
float tiltCurve = (tiltLevel / 100);
tiltCurve = tiltCurve * tiltCurve;
int finalTiltValue = tiltCurve * 100;
if (tiltAmount < 1) { // Checks if playground is not tilted
tiltNeedsCenter = false;
}
if (!tiltNeedsCenter && finalTiltValue > 40) {
playerAction = 2;
tiltNeedsCenter = true; // must re-center before next tilt
delay(200);
}
}
// Giving player feedback for actions
// Light up pixels to show what the player just did
if (playerAction == 0) {
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 0, 0, 255);
}
else if (playerAction == 1) {
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 255, 255, 0);
}
else if (playerAction == 2) {
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 255, 255, 255);
}
// How long the feedback shows before getting cleared
delay(300);
CircuitPlayground.clearPixels();
// Compare player input to expected
if (playerAction != expected) {
// FAIL = flash red and restart
for (int t = 0; t < 3; t++) {
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 255, 0, 0);
delay(200);
CircuitPlayground.clearPixels();
delay(200);
}
// restart the game
roundLength = 1;
sequence[0] = random(0, 3);
return; // exit loop() early and start over
}
}
// Handles player success
for (int t = 0; t < 3; t++) {
for (int p = 0; p < 10; p++) CircuitPlayground.setPixelColor(p, 0, 255, 0);
delay(200);
CircuitPlayground.clearPixels();
delay(200);
}
// Add one more step to the pattern for the next round
if (roundLength < 50) {
sequence[roundLength] = random(0, 3);
roundLength++;
}
delay(300);
}
Analog Team 22
By: Jesse Smith and Jonathan Tsigas
Our game is themed on solving a combination lock that combines rotating and aligning the Circuit Playground with illuminated LEDs. Each round, a distinct LED will glow, and the player has to move the Circuit Playground to get the "Key" LED to align with the "Lock" LED. Once the player believes the LEDs are aligned, they press the button to set that lock in. That sequence will occur three times, making the player solve three separate lock mechanisms to unlock the complete lock. Once all three locks are solved, the player must shake the Circuit Playground to try to open the lock. If they successfully unlock all three locks, then all the lights will glow green, and they will move onto the next level. If they did not do it correctly, all of the lights will glow red, and they will have to restart the level.
The switch on the CPE turns the game on and off.
#include <Adafruit_CircuitPlayground.h> #include <Adafruit_Circuit_Playground.h> const int led = 13; const int slideSwitch = 7; int neoState = 0; int i = 0; int mappedValue = 0; int previousValue = 0; bool showedCombination = false; unsigned long previousTime = 0; int lock1 = 0; int lock2 = 0; int lock3 = 0; const int ButtonPin = A3; bool lockFailed = false; int currentLock = 0; int Locks[3]; int shakeThresh = 25; //const int buttonA = 4; void setup() { // put your setup code here, to run once: pinMode(led, OUTPUT); //pinMode(buttonA, INPUT_PULLDOWN); //pinMode(CPLAY_RIGHTBUTTON, INPUT_PULLUP); Serial.begin(9600); CircuitPlayground.begin(); pinMode(ButtonPin, INPUT); randomSeed(micros()); //pinMode(buttonA, INPUT_PULLUP); delay(2000); } void loop() { // put your main code here, to run repeatedly: //Serial.println("Hi"); // Serial.println(analogRead(A2)); //Serial.println(digitalRead(ButtonPin)); if (showedCombination == false) { showCombination(); } previousValue = mappedValue; i = analogRead(A2); mappedValue = map(i, 0, 1024, 0, 10); // Serial.println(mappedValue); if (previousValue != mappedValue) { CircuitPlayground.setPixelColor(previousValue, 0, 0 , 0); } CircuitPlayground.setPixelColor(mappedValue, 30, 10, 100); if (digitalRead(ButtonPin)) { //Serial.println("Num picked"); if (mappedValue != Locks[currentLock]) { Serial.println("wrong"); lockFailed = true; } else if (mappedValue == Locks[currentLock]) { Serial.println("correct"); } currentLock++; delay(500); } float shake = abs(CircuitPlayground.motionX()) + abs(CircuitPlayground.motionY()) + abs(CircuitPlayground.motionZ()); Serial.println(shake); if (shake > shakeThresh && currentLock == sizeof(Locks) / sizeof(Locks[0])) { if (lockFailed) { for (int b = 0; b <= 9; b++) { CircuitPlayground.setPixelColor(b, 255, 0, 0); } } else if (!lockFailed) { for (int b = 0; b <= 9; b++) { CircuitPlayground.setPixelColor(b, 0, 255, 0); } } } } void showCombination() { for (int y = 0; y < sizeof(Locks) / sizeof(Locks[0]); y++) { Locks[y] = random(10); Serial.println(Locks[y]); CircuitPlayground.setPixelColor(Locks[y], 30, 10, 100); delay(500); CircuitPlayground.setPixelColor(Locks[y], 0, 0, 0); delay(500); showedCombination = true; } }

