20 November 2024

Team 6 Cuphead Controller


Our controller is conceptually based off of Cuphead using a mug or "cup" as the controller design itself. The controller uses the Built in accelerometer to move left or right using the Y axis to determine if Cuphead will move to the left or right. Using the X axis, flicking the controller up on the X axis will make cuphead jump. Using the potentiometers' range of 341-682, when turned into that range it will  switch weapons by sending an input for the Tab key. The final input is a photoresistor on the handle that when exposed to light will trigger a constant X key input like you are holding down the key and when exposed to a lack of light will cause the input to stop. The controller itself is supposed to be ergonomic like how a mug would be when held for an ease of access and the controls are meant to be like your using a mug with using the metal straw to "stir" the potentiometer into the threshold for pressing Tab, tilting the drink is like sloshing the liquid around to make it go in certain directions, and flicking or "drinking" will make the character jump while the photoresistor doesn't really have a true theme but fits into the mug handle for conceptual design.  

One important question for all of you:

If there was one thing that you could change about the controller to make it more appealing or functional, what would it be?








Work Contributed: 
    Alexander Corliss - Mainly did the code itself on the controller and did a lot of testing on the design's code as well as the wiring for the circuit. Helped a bit on physical controller construction and finishing touches for the controller.

Michael Doctor - Came up with the original concept and design for the control, drew up the schematics for the circuitry, modeled and printed the physical shell of the controller with refinement to the original design, and helped construct the physical shell with piecing everything together.


// Alexander Corliss & Michael Doctor Cuphead Controller
#include <Adafruit_CircuitPlayground.h>
#include <Keyboard.h>

const float tiltThreshold = 1.0;    // Threshold for detecting left/right tilt
const float jumpThreshold = -0.5;   // Threshold for detecting upward flick
const float downTiltThreshold = -1.0; // Threshold for detecting downward tilt
const int potMinRange = 341;        // Minimum potentiometer value for Tab key
const int potMaxRange = 682;        // Maximum potentiometer value for Tab key
const int switchPin = A2;           // Digital pin for the separate switch

bool canJump = true;                // To prevent multiple jumps
bool leftPressed = false;           // Left arrow key
bool rightPressed = false;          // Right arrow key
bool downPressed = false;           // Down arrow key                                                                                                                                                                        
bool tabPressed = false;            // Track if Tab was pressed
bool xHeld = false;                 // Tracks the X input being held down

void setup() {
  CircuitPlayground.begin();
  Keyboard.begin();
  pinMode(switchPin, INPUT_PULLUP); // Configure A2
  delay(500);                       // Give some time for initialization
}

void loop() {
  // Check if the slide switch is off
  if (!CircuitPlayground.slideSwitch()) {
    // If off, release all keys and skip processing
    if (leftPressed) {
      Keyboard.release(KEY_LEFT_ARROW);
      leftPressed = false;
    }
    if (rightPressed) {
      Keyboard.release(KEY_RIGHT_ARROW);
      rightPressed = false;
    }
    if (downPressed) {
      Keyboard.release(KEY_DOWN_ARROW);
      downPressed = false;
    }
    if (xHeld) {
      Keyboard.release('x');
      xHeld = false;
    }
    return;
  }

  // Read accelerometer data for tilt and flick
  float x = CircuitPlayground.motionX();
  float y = CircuitPlayground.motionY(); // Forward/backward tilt
  float z = CircuitPlayground.motionZ();

  // Move Left with Left Tilt
  if (x < -tiltThreshold) {
    if (!leftPressed) {
      Keyboard.press(KEY_LEFT_ARROW);
      leftPressed = true;
    }
  } else if (leftPressed) {
    Keyboard.release(KEY_LEFT_ARROW);
    leftPressed = false;
  }

  // Move Right with Right Tilt
  if (x > tiltThreshold) {
    if (!rightPressed) {
      Keyboard.press(KEY_RIGHT_ARROW);
      rightPressed = true;
    }
  } else if (rightPressed) {
    Keyboard.release(KEY_RIGHT_ARROW);
    rightPressed = false;
  }

  // Crouch or Move Down with Down tilt
  if (y < downTiltThreshold) {
    if (!downPressed) {
      Keyboard.press(KEY_DOWN_ARROW);
      downPressed = true;
    }
  } else if (downPressed) {
    Keyboard.release(KEY_DOWN_ARROW);
    downPressed = false;
  }

  // Z input for Jumping in game
  if (z < jumpThreshold && canJump) {
    Keyboard.press('z');
    delay(100);  // Delay for Key Press
    Keyboard.release('z');
    canJump = false; // Prevents Multiple Jump inputs at once
  }

  if (z > -jumpThreshold) {
    canJump = true;
  }

  // Potentiometer Code for Tab Key Input
  int potValue = analogRead(A3); // Reading the Analog Values
  if (potValue >= potMinRange && potValue <= potMaxRange) {
    if (!tabPressed) {
      Keyboard.press(KEY_TAB);
      delay(100);  //
      Keyboard.release(KEY_TAB);
      tabPressed = true; // Prevents Constant input if in Analog Range
    }
  } else {
    tabPressed = false; // Allows Tab to be inputed again
  }

  // For Shooting or X key Input
  int switchState = digitalRead(switchPin);
  if (switchState == LOW) {          
    if (!xHeld) {
      Keyboard.press('x');           // Allows for constant X input
      xHeld = true;
    }
  } else {                           // Turns off the X input and stops shooting
    if (xHeld) {
      Keyboard.release('x');        
      xHeld = false;
    }
  }

  delay(50);
}





























No comments:

Post a Comment

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