Co-op League of Legends Controller
https://youtu.be/9FyNy_wmSOw
The idea for our controller came from our team's shared enjoyment of the game League of Legends and its lore. We wanted to pay tribute to one of the game's artifacts with a great backstory, a pair of powerful gauntlets that ended up in the hands of two different people; therefore, we decided on two different controllers in the form of Ezreal and Kassadin's gauntlets. One controls movement and skillshot direction mirroring a ranged adc (ezreal), while the other is used to fire abilities mirroring the ability-based assassin (kassadin). The idea is you would play League cooperatively with two people, each using one gauntlet, but one person could play with both gauntlets as well. The novelty of engaging in gameplay in a new manner (coop) and the lore representation seek to give the player an enjoyable, social way of playing a famously toxic and stressful game.
Question: Do you think that making the controllers character specific in the game as well would make the design better and have a stronger thematic and give more room to explore better thematic to mechanic ties?
Reference:
Ezreal with his gauntlet
Kassadin with his gauntletEzreal's Gauntlet#include <Adafruit_CircuitPlayground.h> #include <Adafruit_Circuit_Playground.h> #include <Mouse.h> #include <Keyboard.h> #include <Wire.h> #include <SPI.h> void setup() { // put your setup code here, to run once: // put your setup code here, to run once: CircuitPlayground.begin(); Serial.begin(9600); Mouse.begin(); Keyboard.begin(); CircuitPlayground.setBrightness(60); for(int i = 0; i < 9; i++){ CircuitPlayground.setPixelColor(i,128,0,128); }
CircuitPlayground.setAccelRange(LIS3DH_RANGE_2_G); //need to create a variable to store the mouses last know position from the center point // Using mouse libraray exmaple code as a base lets cook } // the loop routine runs over and over again forever: void loop() { // read the input on analog pin A0: int analogValue = analogRead(A3); // Rescale to potentiometer's voltage (from 0V to 5V): float voltage = analogValue * (3.3/ 1023); if(analogValue > 240){ Keyboard.press('q'); delay(75); Keyboard.release('q'); } if(analogValue > 240 && analogValue < 300){ Keyboard.press('w'); delay(75); Keyboard.release('w'); } if(analogValue > 300){ Keyboard.press('e'); delay(75); Keyboard.release('e'); }
// print out the value you read: Serial.print("Analog: "); Serial.print(analogValue); Serial.print(", Voltage: "); Serial.println(voltage); }- char getMappedChar(int analogValue) { // Define the ranges for each character with dead zones const int deadZoneSize = 10; // Size of each dead zone const int charRanges[] = {163, 162, 162, 162, 162, 162}; // Sizes for q, w, e, r, d, f const char chars[] = {'q', 'w', 'e', 'r', 'd', 'f'}; int start = 0; for (int i = 0; i < 6; i++) { int end = start + charRanges[i] - 1; // End of current char's range if (analogValue >= start && analogValue <= end) { return chars[i]; } start = end + 1 + deadZoneSize; // Skip the dead zone } return '\0'; // Return null if out of range (shouldn't happen for 0-1022) } void setup() { Serial.begin(9600); } void loop() { // Simulate an analog input (0-1023) for testing int simulatedValue = random(0, 1023); char mappedChar = getMappedChar(simulatedValue); Serial.print("Value: "); Serial.print(simulatedValue); Serial.print(" → Mapped Char: "); Serial.println(mappedChar); delay(500); // Slow down output for readability }
- char getMappedChar(int analogValue) { const int deadZoneSize = 50; // Increased dead zone size const int charRanges[] = {129, 129, 129, 129, 129, 128}; // q, w, e, r, d, f const char chars[] = {'q', 'w', 'e', 'r', 'd', 'f'}; int start = 0; for (int i = 0; i < 6; i++) { int end = start + charRanges[i] - 1; // End of current char's range if (analogValue >= start && analogValue <= end) { return chars[i]; } start = end + 1 + deadZoneSize; // Skip dead zone } return '\0'; // Out of range (1023 is unused) } void setup() { Serial.begin(9600); } void loop() { // Simulate analog input (0-1023) int simulatedValue = random(0, 1023); char mappedChar = getMappedChar(simulatedValue); Serial.print("Value: "); Serial.print(simulatedValue); Serial.print(" → Mapped Char: "); Serial.println(mappedChar); delay(500); }
- switch (mappedChar) { case 'q': Serial.println("Action: Q pressed!"); // Your code for 'q' here break; case 'w': Serial.println("Action: W pressed!"); // Your code for 'w' here break; case 'e': Serial.println("Action: E pressed!"); // Your code for 'e' here break; case 'r': Serial.println("Action: R pressed!"); // Your code for 'r' here break; case 'd': Serial.println("Action: D pressed!"); // Your code for 'd' here break; case 'f': Serial.println("Action: F pressed!"); // Your code for 'f' here break; default: Serial.println("No action (dead zone or out of range)"); break;
- ''#include <Adafruit_CircuitPlayground.h> #include <Adafruit_Circuit_Playground.h> #include <Mouse.h> #include <Wire.h> #include <SPI.h> int range = 12; int delayTimer = 2; int center = range/2; int threshold = range / 4; float minMotionx = 1; float maxMoition = 10; bool on = false; void setup() { // put your setup code here, to run once: // put your setup code here, to run once: CircuitPlayground.begin(); Serial.begin(9600); Mouse.begin(); CircuitPlayground.setBrightness(75); for(int i = 0; i < 9; i++){ CircuitPlayground.setPixelColor(i,0,0,128); }
CircuitPlayground.setAccelRange(LIS3DH_RANGE_2_G); //need to create a variable to store the mouses last know position from the center point // Using mouse libraray exmaple code as a base lets cook
} float AccelReader(){ float x = 0; float y = 0; float z = 0; //Should it be a one time read on call or should i have a read for a set Time? //The examples I've seen have had a fixed read but i think that wil for(int i = 0; i < 15; i++){ x += CircuitPlayground.motionX(); y += CircuitPlayground.motionY(); z += CircuitPlayground.motionZ();
} //might need to trim these to be an average or make a buffer return sqrt(xx + yy + zz); } float lerp(float x, float x0, float x1, float y0, float y1) { // Check if the input value (x) is outside its desired range and clamp to // those min/max y values. if (x <= x0) { return y0; } else if (x >= x1) { return y1; } // Otherwise compute the value y based on x's position within its range and // the desired y min & max. return y0 + (y1-y0)((x-x0)/(x1-x0)); } void loop() { // put your main code here, to run repeatedly: if(CircuitPlayground.leftButton() == HIGH && on == false){ on = true; } if(CircuitPlayground.rightButton() == HIGH && on == true){ on = false; } if(on){ float inputX = CircuitPlayground.motionX(); Serial.println(CircuitPlayground.motionX()); float inputY = CircuitPlayground.motionY(); Serial.println(CircuitPlayground.motionY()); float x_mag = abs(inputX); float x_mouse = lerp(x_mag, minMotionx, maxMoition, 0.0, 12); float y_mag = abs(inputY); float y_mouse = lerp(y_mag, minMotionx, maxMoition, 0.0, 12); // Change the mouse direction based on the direction of the acceleration. if (inputX < 0) { x_mouse = -1.0; } if (inputY < 0) { y_mouse= -1.0; }
//int mouseX = Mapping(inputX, 0); //Serial.println(inputX); //int mouseY = Mapping(inputY, 1); //Serial.println(inputY); Mouse.move((int)x_mouse, (int)y_mouse, 0); delay(10); if(CircuitPlayground.slideSwitch()){ Mouse.click(MOUSE_RIGHT); } } }''' - Kassadin's Gauntlet
- #include <Adafruit_CircuitPlayground.h> #include <Adafruit_Circuit_Playground.h> #include <Mouse.h> #include <Keyboard.h> #include <Wire.h> #include <SPI.h> //splits the analog value across 6 values and assigns a button to each range char getMappedChar(int analogValue) { const int deadZoneSize = 50; // dead zone size between values const int charRanges[] = {129, 129, 129, 129, 129, 128}; // q, w, e, r, d, f const char chars[] = {'q', 'w', 'e', 'r', 'd', 'f'}; int start = 0; for (int i = 0; i < 6; i++) { int end = start + charRanges[i] - 1; // End of current char's range if (analogValue >= start && analogValue <= end) { return chars[i]; } start = end + 1 + deadZoneSize; // Skip dead zone } return '\0'; // Out of range (1023 is unused) } void setup() { // put your setup code here, to run once: // put your setup code here, to run once: CircuitPlayground.begin(); Serial.begin(9600); Mouse.begin(); Keyboard.begin(); CircuitPlayground.setBrightness(60); for(int i = 0; i < 9; i++){ CircuitPlayground.setPixelColor(i,128,0,128); }
CircuitPlayground.setAccelRange(LIS3DH_RANGE_2_G); } bool firing_State; // the loop routine runs over and over again forever: void loop() { while (CircuitPlayground.slideSwitch()) { int analogValue = analogRead(A1); // Rescale to potentiometer's voltage (from 5v to 3.3V): float voltage = analogValue * (3.3/ 1023); char keypress = getMappedChar(analogValue); //can fire if (CircuitPlayground.motionX() > 9) { firing_State = true; } //Swapps key press based on potentiometer switch (keypress) { case 'q': if(firing_State){ Serial.println("Action: Q pressed!"); Keyboard.press('q'); delay(100); Keyboard.release('q'); } break; case 'w': if(firing_State){ Serial.println("Action: W pressed!"); Keyboard.press('w'); delay(100); Keyboard.release('w'); } break; case 'e': if(firing_State){ Serial.println("Action: E pressed!"); Keyboard.press('e'); delay(100); Keyboard.release('e'); } break; case 'r': if(firing_State){ Serial.println("Action: R pressed!"); Keyboard.press('r'); delay(100); Keyboard.release('r'); } break; case 'd': if(firing_State){ Serial.println("Action: D pressed!"); Keyboard.press('d'); delay(100); Keyboard.release('d'); } break; case 'f': if(firing_State){ Serial.println("Action: F pressed!"); Keyboard.press('f'); delay(100); Keyboard.release('f'); } break; default: Serial.println("No action (dead zone or out of range)"); break; }
// print out the value you read: Serial.print("Analog: "); Serial.print(analogValue); Serial.print(", Voltage: "); Serial.println(voltage); } } - k
new
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.