20 November 2024

Team 3 Fireboy and Watergirl Controller

 Watergirl Controller

Photo



 

Description

    The conceptual model of the design is a controller modeled after the main characters in the flash game Fireboy and Watergirl. The high-fidelity prototype is specifically modeled after Watergirl. The 3D printed controller has a space in one eye for the potentiometer and the other eye has small holes to signifiy a microphone in the Circuit Playground Express. On the body, there's an opening to place an external switch to be the arm of the model. By flipping the switch, the player gets to choose between playing as Watergirl or Fireboy. This is important because the game requires both characters to be played in order to complete the levels. The direction the potentiometer is turned decides on whether the player moves left or right by pressing down A Key or Left Arrow Key to go left or pressing down D Key or Right Arrow Key to go right. The microphone gets an average of the sound levels in the room, and when there's a sudden spike, the W Key or Up Arrow Key gets pressed down and the player jumps. This mapping between the inputs and outputs enhance the immersive experience by connecting the physical controller to the game's theme.

Schematic

Code

//Chelsea Soto and Molly Guinn
#include <Keyboard.h>
#include <KeyboardLayout.h>
#include <Keyboard_da_DK.h>
#include <Keyboard_de_DE.h>
#include <Keyboard_es_ES.h>
#include <Keyboard_fr_FR.h>
#include <Keyboard_hu_HU.h>
#include <Keyboard_it_IT.h>
#include <Keyboard_pt_PT.h>

#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>

#include <math.h>

// assign pins
const int potent = A4;   // potentiometer middle pin
const int eSwitch = A7;  // external switch middle pin
const int redLED = A3;
const int blueLED = A2;

// constant variables
const int debounce = 100;                     // Debounce time in ms for each sound check
const int threshold = 5;                      // Sound threshold for jumping
const int valueNum = 10;                      // Number of values to calculate average sound level
unsigned long lastAverageTime = 0;            // Timer for average calculation
const unsigned long averageInterval = 15000;  // Time in ms between average calculations

float baselineAverage = 0.0;  // Store initial baseline

void setup() {
  // initialize libraries
  CircuitPlayground.begin();
  Keyboard.begin();

  // serial initialization
  Serial.begin(9600);

  // initialize pins
  pinMode(potent, INPUT);          // potentiometer
  pinMode(eSwitch, INPUT_PULLUP);  // external switch
  pinMode(redLED, OUTPUT);         // red LED for Fireboy
  pinMode(blueLED, OUTPUT);        // blue LED for Watergirl

  // Set initial LED states to off
  digitalWrite(redLED, LOW);
  digitalWrite(blueLED, LOW);

  // Calculate initial baseline
  baselineAverage = checkAverage(valueNum);
}

void loop() {
  // Check if the slide switch is on
  if (digitalRead(CPLAY_SLIDESWITCHPIN)) { // for debug purposes only

    // Check if it's time to recalculate the baseline average
    if (millis() - lastAverageTime >= averageInterval) {
      baselineAverage = checkAverage(valueNum);
      lastAverageTime = millis();
    }

    // Check switch state for mode selection
    bool mode = digitalRead(eSwitch) == LOW;

    // Potentiometer value check
    int potValue = analogRead(potent);

    // FIREBOY CONTROLS
    if (mode) {
      // LEDs
      digitalWrite(redLED, HIGH);  // Turn on red LED for Fireboy
      digitalWrite(blueLED, LOW);  // Ensure blue LED is off

      // Movement
      if (potValue < 462) {  // Move right
        Keyboard.press(KEY_RIGHT_ARROW);
        Keyboard.release(KEY_LEFT_ARROW);
      } else if (potValue > 562) {  // Move left
        Keyboard.press(KEY_LEFT_ARROW);
        Keyboard.release(KEY_RIGHT_ARROW);
      } else {  // No movement
        Keyboard.release(KEY_LEFT_ARROW);
        Keyboard.release(KEY_RIGHT_ARROW);
        Serial.println("not moving");
      }

      // Sound check for jumping
      float currentValue = CircuitPlayground.soundSensor();
      float difference = baselineAverage - currentValue;
      if (difference >= threshold) {
        Keyboard.press(KEY_UP_ARROW);  // Jump
      } else {
        Keyboard.release(KEY_UP_ARROW);  // Stop jump
      }
    }

    // WATERGIRL CONTROLS
    else {
      // LEDs
      digitalWrite(blueLED, HIGH);  // Turn on blue LED for Watergirl
      digitalWrite(redLED, LOW);    // Ensure red LED is off

      // Movement
      if (potValue < 462) {  // Move right
        Keyboard.press('d');
        Keyboard.release('a');
      } else if (potValue > 562) {  // Move left
        Keyboard.press('a');
        Keyboard.release('d');
      } else {  // No movement
        Keyboard.release('a');
        Keyboard.release('d');
        Serial.println("not moving");
      }

      // Sound check for jumping
      float currentValue = CircuitPlayground.soundSensor();
      float difference = baselineAverage - currentValue;
      if (difference >= threshold) {
        Keyboard.press('w');  // Jump
      } else {
        Keyboard.release('w');  // Stop jump
      }
    }

    // Small delay to avoid switch debounce issues
    delay(50);
  }
}

// Function to check the average sound level
float checkAverage(int valueNum) {
  float valueSum = 0.0;
  unsigned long lastDebounceTime = 0;
  int count = 0;

  while (count < valueNum) {
    if (millis() - lastDebounceTime >= debounce) {
      lastDebounceTime = millis();
      float currentValue = CircuitPlayground.soundSensor();
      valueSum += currentValue;
      count++;
      Serial.print("Current sound level: ");
      Serial.println(currentValue);
    }
  }

  float average = valueSum / valueNum;

  Serial.print("AVERAGE SOUND LEVEL: ");
  Serial.println(average);

  return average;
}

Video

Here is the YouTube video showing that the code is works during the low-fidelity prototype.

Right now we're having issues getting the high-fidelity prototype to work with the new controller casing and wires. We have an idea where the issue could be and are planning to gut it and restart the process for Tuesday.

UPDATE: 11/21/2024

We were able to fix it after class!

Questions

1. Should the controller be more modeled after the characters (flames or water drop) or just be different colors?
The design is meant to have two controllers, but because of time frame there is only one, being red and blue respective to the default controller characters.

2. What is another way we could achieve the left/right and jump movement, without making a Wii move controller?

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.