26 April 2026

Final Project Team 8: Hidden Folks Game Controller


Our game controller is made to reflect the theme of the game Hidden Folks. In the game, players must search through mini landscapes to find certain people, things, or objects. The game, which consists of a black and white color palette, has simple inputs, consisting of zoom in/zoom out buttons, a select button, and a pan button to move across the landscape.Due to the overall simplistic nature of the game, we chose to carry the theme into the controller by creating a treasure map controller. The controller consists of two cylinders and a middle portion, which simultaneously give the player somewhere to grab onto and also visually represent the two scroll portions of an ancient map. The middle portion is decorated overtop with a handdrawn map, integrating both a light sensor and a touchpad into the layout.

Controller Image:


Schematic:


Code:

#include <Mouse.h>
#include <Adafruit_CircuitPlayground.h>

// ---------------- PINS ------------------
// making variables for each pin and what it connects to on the CPE
const int fsrPin = A1;
const int lightSensorPin = A2;
const int potPin = A3;

// ---------------- STATES ----------------
// variables used for keeping info to reference later
bool leftHeld = false;
int lastPotValue = 0;

// ---------------- SETUP -----------------
void setup() {
  // circuit and mouse tracking, along with the 3 analog inputs
  Serial.begin(9600);
  CircuitPlayground.begin();
  Mouse.begin();
  pinMode(fsrPin, INPUT);
  pinMode(lightSensorPin, INPUT);
  lastPotValue = analogRead(potPin);
}

// ---------------- LOOP FUNCTIONS ------------------
void loop() {
  // repeated functions
  handleSensors();
  handleTilt();
  handlePot();
  //lightCheck();
  //fsrCheck;
 
  delay(10);
}

/*void lightCheck() {
  // checking light values
  int lightVal = analogRead(lightSensorPin);
  Serial.print("Light Sensor Value: ");
  Serial.println(lightVal);

  delay(200);
}
*/

/*void fsrCheck() {
  // checking pressure values
  int fsrReading;
  fsrReading = analogRead(fsrPin);
  Serial.print("Analog Reading = ");
  Serial.print(fsrReading);

  delay(200);
}
*/

// ---------------- SENSOR HANDLING ----------------
void handleSensors() {
  // variables to get readings on each sensor / how it activates
  int fsrVal = analogRead(fsrPin);
  int lightVal = analogRead(lightSensorPin);
  bool fsrPressed = fsrVal > 500;              // pressure pad threshold
  bool lightTriggered = lightVal < 600;        // darkness threshold

  // ---------- PRESSURE PAD = HOLD ------------
  // hold down mouse when fsr pressure increases
  if (fsrPressed && !leftHeld) {
    Mouse.press(MOUSE_LEFT);
    leftHeld = true;
  }
  else if (!fsrPressed && leftHeld) {
    Mouse.release(MOUSE_LEFT);
    leftHeld = false;
  }

  // ---------- LIGHT SENSOR = PRESS ----------
  // light sensor activating in darkness presses left click
  static bool lastLightState = false;
  if (lightTriggered && !lastLightState) {
    Mouse.click(MOUSE_LEFT);
  }
  lastLightState = lightTriggered;
}

// ---------------- TILT ----------------
// tilt movement around the screen, adjusting speed as needed
void handleTilt() {
  float x = CircuitPlayground.motionX();
  float y = CircuitPlayground.motionY();
  int moveX = x * 2;
  int moveY = y * 2;
  // dead zone
  if (abs(moveX) < 2) moveX = 0;
  if (abs(moveY) < 2) moveY = 0;
  Mouse.move(moveX,moveY);

// ---------------- POTENTIOMETER ----------------
void handlePot() {
  // potentiometer zooms in and out
  int potValue = analogRead(potPin);
  static int lastPotValue = 0;
  // smooth the reading
  static int potFiltered = 0;
  potFiltered = (potFiltered * 3 + potValue) / 4;

  int diff = potFiltered - lastPotValue;

  if (abs(diff) > 25) {
    int scrollAmount = diff / 30;

    // ignore zoom if fsr or light is active
    if (!leftHeld) {
      Mouse.move(0, 0, scrollAmount);
    }

    lastPotValue = potFiltered;
  }
}

Video:

No comments:

Post a Comment

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