Week 12 – Final Project Proposal

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


Leave a Reply