My final project is a bomb defusal game inspired by Keep Talking and Nobody Explodes. Just like in the original game, the player has to disarm several modules on the bomb in order to successfully defuse it. Currently I plan to include four types of modules. The first is Simon Says, using four buttons and corresponding LEDs. The second is a single larger button connected to a multicolored LED, which will be disarmed differently depending on the color. The third is an adaptation of cutting wires, where the player will have to either disconnect or rearrange the wires correctly. The last module requires the user to use a potentiometer as a tuning knob and try to hone in on the correct frequency.
The Arduino will be responsible for reading the inputs from each module, and correctly lighting the LEDs where needed. I also intend to use the display screen from our kits to show the bomb’s timer if possible, and use a buzzer/speaker to create a beeping noise. The p5.js side will be responsible for initializing a new game and managing its state. It will receive the inputs from Arduino and verify them, and send back the confirmation if a module was completed. I also want to use it to render a representation of the bomb, including the correct LED lights and countdown timer. In line with the original game, it can also work to provide the information needed to disarm the more complicated modules. In terms of interaction, p5.js will be used to start the game and will display a win/loss screen after it ends.
I have started writing some basic code for both components:
/* Final Project (WIP) By Matthias Kebede */ // // // Global Variables // // Inputs const int tempIn = A1; // // Outputs const int tempOut = 8; const int speakerPin = 10; // // Communication and State Information int sendInterval = 100; # ms int lastSendTime = 0; # ms int timer = [5, 0]; # minutes, seconds int beepFreq = 1000; # hz int beepDur = 50; # ms int beepInterval = 100; # ms int lastBeepTime = 0; // // // Main Processes void setup() { Serial.begin(9600); // // Inputs and Outputs pinMode(tempIn, INPUT); pinMode(LED_BUILTIN, OUTPUT); pinMode(tempOut, OUTPUT); // // Check built-in LED digitalWrite(LED_BUILTIN, HIGH); delay(200); digitalWrite(LED_BUILTIN, LOW); // // Start handshake w/ p5.js while (Serial.available() <= 0) { digitalWrite(LED_BUILTIN, HIGH); Serial.println("123"); // identifiable starting number delay(300); digitalWrite(LED_BUILTIN, LOW); delay(50); } } void loop() { // // Wait for p5.js while (Serial.available()) { digitalWrite(LED_BUILTIN, HIGH); int firstVal = Serial.parseInt(); if (Serial.read() == '\n') { analogWrite(tempOut, firstVal); } if (lastSendTime > sendInterval) { lastSendTime = 0; int sendVal = analogRead(tempIn); int mappedVal = map(sendVal, low, high, 0, 255); Serial.println(sendVal); delay(1); // stabilize ADC? check this } else { lastSendTime++; } digitalWrite(LED_BUILTIN, LOW); } } // // // Helper Functions void timerSound() { if (lastBeepTime > beepInterval) { // // Less than 30 seconds remaining if (timer[0] == 0 && timer[1] < 30) { tone(speakerPin, beepFreq + 500, beepDur); } // // Final minute but more than 30 seconds else if (timer[0] == 0) { tone(speakerPin, beepFreq + 250, beepDur + 25); } else { tone(speakerPin, beepFreq, beepDur + 50); } } else { lastBeepTime++; } }
/* Final Project By Matthias Kebede */ // // // Global Variables let debug = true; let gameState = 'menu'; // menu, playing, win, lose let game; // // For display let play, menuTitle; // // // Main Processes function preload() { } function setup() { createCanvas(600, 450); createMenu(); } function draw() { background(220); switch (gameState) { case 'menu': showMenu(); break; case 'playing': game.display(); break; default: break; } } // // // Classes class Game { constructor() { this.gameover = false; this.start = millis(); this.time = 30; this.modules = []; } display() { text(`Time: ${Math.floor(this.time)}`, width/2, height/2); if (!this.gameover) { this.update(); } else { text("Gameover", width/2, height*0.2); } } update() { for (let module in modules) { module.checkStatus(); } // // Update timer if (this.time > 0 + 1/frameRate()) { this.time -= 1/frameRate(); } else { this.time = 0; this.gameover = true; } } } class Module { constructor() {} checkStatus() {} } // // // Interaction function mouseClicked() {} // // // Displays function createMenu() { // // Menu Title menuTitle = createElement('h1', "Main Menu"); menuTitle.size(9*18, 100); menuTitle.position((width-menuTitle.width)/2, height*0.2); // // Play Button play = createButton("Play"); play.size(width/5, height/15); play.position((width-play.width)/2, height/2); play.mousePressed(function() { game = new Game(); gameState = 'playing'; removeElements(); }); } function showMenu() {} // // // Helper Functions