19 April 2025

Excitebike Game Controller

Team 14: Spencer Williams and Ethan Lopez-Rojas

We made a controller for Excitebike. Our conceptual model was based on the handlebars on a bike; with the mechanics aimed at being intuitive based on the action performed. Revving on the handlebars controls acceleration, leaning forward and back controls the leaning in game, and you turn the handlebar to switch lanes. We mapped the lean controls to the accelerometer in the Circuit Playground Express to detect when the player is leaning, and we used 2 potentiometers to detect the throttle on each handlebar and one connected to the bottom of the center tube to detect turning for lane switching. As for signifiers, our conceptual model being handlebars allows us to signify to the player easily how to rev up for acceleration and turning the handlebars to switch lanes as most people have ridden a bike or know the basics of it. For feedback, revving up the handlebars will cause the engine in game to start going allowing for 1:1 visual feedback form performing the actions the driver in game would have to. Performing the actions required by a bike rider was the main theme for our controller, creating an immersive and intuitive gaming experience. For our one question: How well do the controls reflect the real-world actions of riding a bike, and are there any ways we could make them feel even more natural or intuitive?

Contributions: 

We worked collaboratively on the initial ideation. Spencer did most of the actual building and making sure the prints went well with Ethan assisting with it a bit. Ethan did most of the coding with Spencer testing and adjusting numbers and slight code where need be. 


#include <Adafruit_CircuitPlayground.h>
#include <Keyboard.h> //analog inputs float slowPo; //slow accel float fastPo; //fast accel float turnPo; //switching lanes float lean; //wheelies and air balance //thresholds for inputs (adjusted per testing and default potentiometer position) const float slowThreshold = 0.35; const float fastThreshold = 0.35; const float turnLeftThreshold = 2; const float turnRightThreshold = -2; const float leanBackThreshold = -0.25; const float leanForwardThreshold = 0.75; void setup() { Serial.begin(9600); CircuitPlayground.begin(); Keyboard.begin(); } void loop() { // only runs when the switch is flipped if (CircuitPlayground.slideSwitch()){ //read potentiometer values (0-1023) and map them to appropriate ranged slowPo = map(analogRead(A1), 0, 1023, 0, 1); fastPo = map(analogRead(A6), 0, 1023, 0, 1); turnPo = map(analogRead(A3), 0, 1023, -10, 10); //read accelerometer Y-axis for lean lean = CircuitPlayground.motionY(); lean = map(lean, -10, 10, -1, 1); //map to -1 - 1 //slow accel, we do less than since the rotation of the potentiometer would mean rotating it // towards the player would be decreasing the value instead of increasing the value. if (slowPo <= slowThreshold) { Keyboard.release('z'); Keyboard.press('x'); } else { Keyboard.release('x') ; } //fast accel if (fastPo >= fastThreshold) { Keyboard.release('x') ; Keyboard.press('z'); //Serial.println("fast accel"); } else { Keyboard.release('z'); } //turn left if (turnPo <= turnLeftThreshold) { Keyboard.release(KEY_DOWN_ARROW); Keyboard.press(KEY_UP_ARROW); } else { Keyboard.release(KEY_UP_ARROW) ; } //turn right if (turnPo >= turnRightThreshold) { Keyboard.release(KEY_UP_ARROW); Keyboard.press(KEY_DOWN_ARROW); } else{ Keyboard.release(KEY_DOWN_ARROW); } //lean back if (lean <= leanBackThreshold) { Keyboard.release(KEY_RIGHT_ARROW); Keyboard.press(KEY_LEFT_ARROW); } else{ Keyboard.release(KEY_LEFT_ARROW); } //lean forward if (lean >= leanForwardThreshold) { Keyboard.release(KEY_LEFT_ARROW); Keyboard.press(KEY_RIGHT_ARROW); } else{ Keyboard.release(KEY_RIGHT_ARROW); } delay(debugDelay);
} }


 



No comments:

Post a Comment

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