27 November 2023

Game Controller: Five Night's at Freddy's

Vision & Disclaimer 

For the final project I decided to create a game controller for Five Nights at Freddy's. Taking into consideration the gameplay and theming I decided to turn the laptop the player uses in-game into the controller in an attempt to better immerse the player in the gameplay. One of the biggest challenges I faced was realizing that FnAF isn't actually played using any hotkeys or keyboard controls and is only controlled using the mouse. Given that, I must state as a disclaimer, that I found external code that takes keyboard commands and converts it into mouse movements on the screen, thus emulating how FnAF could be played with only the keyboard.

Controller Description

 With that sorted, here's the description for the actual controller. The "laptop" would sit on the player's lap or on the desk in front of them and then be controlled using the various sensors. When the "laptop" is opened, the laptop in game is opened to view the cameras, and then using the potentiometer and the position switch the player can cycle through each of the cameras; closing the laptop of course closes it in game as well. The position switch is used to control the doors while the "laptop" is closed, and the potentiometer and photoresistor work in tandem to turn the lights on and off depending on brightness and position of the potentiometer.

Peer Question

Although the player would be looking at the actual computer screen most times do you think more visual aids on the controller itself would be useful?












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

//HID report descriptor using TinyUSB's template
//Single report (no ID) descriptor
uint8_t const desc_hid_report[] =
{
  TUD_HID_REPORT_DESC_KEYBOARD()
};

// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
//https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h


float y; //CPB Accelerometer
bool computerOpen = false; //check if screen is opened
bool leftDoorClosed = false; // check if left door is closed
bool rightDoorClosed = false; // check if right door is closed

//Check if cameras are active
bool cam0 = false;
bool cam1 = false;
bool cam2 = false;
bool cam3 = false;
bool cam4 = false;
bool cam5 = false;
bool cam6 = false;
bool cam7 = false;
bool cam8 = false;
bool cam9 = false;
bool cam1A = false;
bool cam2B = false;
//check if lights are on
bool leftLight = false;
bool rightLight = false;
void setup() {
  CircuitPlayground.begin();
  usb_hid.begin();
  pinMode(CPLAY_SLIDESWITCHPIN, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP); //Toggle Switch input 1
  pinMode(A5, INPUT_PULLUP);//Toggle Switch input 2
  Serial.begin(115200);

  delay(1000);

}

void loop() {
  uint8_t const report_id = 0;  //unsigned 8bit (1 byte) int
  uint8_t modifier = 0;         //used by libraries to save space
  uint8_t keycode[6] = { 0, 0 };   //normal int is 16 bit (4 bytes)

    y = CircuitPlayground.motionY() * -1; //Accelerometer Y value
    int toggleValue1 = analogRead(A1); //toggle switch 1 output
    int toggleValue2 = analogRead(A5); //toggle switch 2 output
    int knobValue = analogRead(A3); //potentiometer values
    int brightness = analogRead(A4); //Photoresistor value
  if(digitalRead(CPLAY_SLIDESWITCHPIN))
  {
    Serial.println(y);
  //Opens and closes computer screen
   if(y > 7.2  && computerOpen == false)
   {
    computerOpen = true;
    keycode[0] = HID_KEY_SPACE;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(50);
    usb_hid.keyboardRelease(0);
    }
   if(y < 4 && computerOpen == true)
   {
    computerOpen = false;
    keycode[0] = HID_KEY_SPACE;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(50);
    usb_hid.keyboardRelease(0);
   }

   //controls left and right doors
   //Left Door close
   if (toggleValue1 >= 900 && toggleValue2 <= 350 && computerOpen == false && leftDoorClosed == false) {
    keycode[0] = HID_KEY_Q;
    leftDoorClosed = true;
    rightDoorClosed = false;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(5);
    usb_hid.keyboardRelease(0);
  }
  //Do nothing if both doors open and switch in middle
  if (toggleValue1 >= 900 && toggleValue2 >= 900 && computerOpen == false) {
    keycode[0] = HID_NULL_STATE;
    leftDoorClosed = false;
    rightDoorClosed = false;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(5);
    usb_hid.keyboardRelease(0);
  }
  //Right Door close
  if (toggleValue2 >= 900 && toggleValue1 <= 350 && computerOpen == false && rightDoorClosed == false) {
    keycode[0] = HID_KEY_P;
    leftDoorClosed = false;
    rightDoorClosed = true;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(5);
    usb_hid.keyboardRelease(0);
  }


  //Controls left and right lights
  //Left light on
   if(knobValue < 500 && brightness >= 850 && computerOpen == false && leftLight == false)
   {
    keycode[1] = HID_KEY_A;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(75);
    leftLight = true;
    usb_hid.keyboardRelease(0);
   }
   //Right light on
    if(knobValue > 600 && brightness >= 850 && computerOpen == false && rightLight == false)
   {
    keycode[1] = HID_KEY_L;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(75);
    rightLight = true;
    usb_hid.keyboardRelease(0);
   }
   //left light off
    if(knobValue < 500 && brightness <= 750 && computerOpen == false && leftLight == true)
   {
    keycode[1] = HID_KEY_A;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(75);
    leftLight = false;
    usb_hid.keyboardRelease(0);
   }
   //Right light off
    if(knobValue > 600 && brightness < 750 && computerOpen == false && rightLight == true)
   {
    keycode[0] = HID_KEY_L;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(75);
    rightLight = false;
    usb_hid.keyboardRelease(0);
   }
   
  //If statements for Num Pad to select cameras
   if(knobValue <=99 && knobValue > 10 && computerOpen == true && cam0 == false)
   {
    cam0 = true;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_0;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=199 && knobValue >99 && computerOpen == true && cam1 == false)
   {
    cam0 = false;
    cam1 = true;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_1;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=299 && knobValue >199 && computerOpen == true && cam2 == false)
   {
    cam0 = false;
    cam1 = true;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_2;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=399 && knobValue >299 && computerOpen == true && cam3 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = true;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_3;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=499 && knobValue >399 && computerOpen == true && cam4 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = true;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_4;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=599 && knobValue >499 && computerOpen == true && cam5 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = true;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_5;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=699 && knobValue >599 && computerOpen == true && cam6 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = true;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_6;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=799 && knobValue >699 && computerOpen == true && cam7 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = true;
    cam8 = false;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_7;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue <=899 && knobValue >799 && computerOpen == true && cam8 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = true;
    cam9 = false;
    keycode[0] = HID_KEY_KEYPAD_8;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(knobValue >=900 && computerOpen == true && cam9 == false)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = true;
    keycode[0] = HID_KEY_KEYPAD_9;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   if(toggleValue1 >= 900 && toggleValue2 <= 200 && computerOpen == true && knobValue < 20)
   {
      cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    cam1A = true;
    cam2B = false;
    keycode[0] = HID_KEY_1;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
      if(toggleValue2 >= 900 && toggleValue1 <= 200 && computerOpen == true && knobValue < 20)
   {
    cam0 = false;
    cam1 = false;
    cam2 = false;
    cam3 = false;
    cam4 = false;
    cam5 = false;
    cam6 = false;
    cam7 = false;
    cam8 = false;
    cam9 = false;
    cam1A = false;
    cam2B = true;
     keycode[0] = HID_KEY_2;
    usb_hid.keyboardReport(report_id, modifier, keycode);
    delay(10);
    usb_hid.keyboardRelease(0);
   }
   }
}

No comments:

Post a Comment

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