27 November 2023

Spaceship Controller


This is my controller which was designed for the game Space Invaders. I mostly wanted my controller to look similar to the spaceship that the player controls in-game while playing Space Invaders. I wanted the player to feel as though they are in the game flying the ship in real-time by using the controller in their hands. This controller uses accelerometers to detect when the player is going left or right which adds to the feeling of being in control of the spaceship as if you are piloting it. The controller also has an external light sensor which is located where the right index finger rests. By covering and uncovering the external light sensor the player is able to decide to hold or not hold the power-ups they get in the game. I made this decision because I wanted the player to really feel like they are firing at the enemy and giving commands to their ship. As for the game, it is a game that is fairly simple. Basically, control a spaceship and must destroy enemies that are shooting projectiles down at you which you must avoid to not get destroyed. The overall gameplay loop and feel of space invaders made me feel that making a spaceship as the controller was the best choice because the players can immerse themselves in the game. The spaceship also gives feedback thanks to the transparent "window" that allows the player to see inside the controls and watch the pixels of where the cockpit of a ship would light up. Lastly, to simplify some of the controls, the left and right movements are based on the wasd that are used in many games to control the directional movement of something, however, because this game has no up or down movement that only leaves left and right which is why you can only tilt the controller left or right for movement and the light sensor is always detecting light and if it goes over a value then the input is made.

Do you think having lights as feedback is enough, or should there be something else to give feedback such as noise?




#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>
#include <bluefruit.h>
#include <math.h>
#define PHOTORESISTOR_PIN A1

BLEDis bledis;
BLEHidAdafruit blehid;

int debounce = 2500;

int shakeThresh = 25;

uint16_t value;
uint8_t pixels;

void setup() {
  // put your setup code here, to run once:

  CircuitPlayground.begin();
  Serial.begin(9600);
  delay(500);
  Bluefruit.begin();
  Bluefruit.setTxPower(4);
  //Configure and Start Device Information Service
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();
  //Start HID
  blehid.begin();
  //Start advertising device funtion
  startAdv();

  //other setup
  pinMode(4, INPUT_PULLDOWN);

}

void loop() {
 
  //Detects if theres movement and lights up some pixels for feedback
  float xAxis = CircuitPlayground.motionX();
  if(xAxis < 0) {
    CircuitPlayground.setPixelColor(2,0,0,map(xAxis, -10, 0, 255, 0));
   
  }
  else {
    CircuitPlayground.setPixelColor(7,0,0,map(xAxis, 0, 10, 0, 255));
  }

  float yAxis = CircuitPlayground.motionY();
  if(yAxis < 0) {
    CircuitPlayground.setPixelColor(0,0,0,map(yAxis, -10, 0, 255, 0));
   
  }
  else {
    CircuitPlayground.setPixelColor(9,0,0,map(yAxis, 0, 10, 0, 255));
  }
 
  //Takes into account the accelerometers for Y and Z to detect if the controller is shaking
  //If the controller is shaked there will be a sounds that plays
  float shake = abs(CircuitPlayground.motionX())
  + abs (CircuitPlayground.motionY())
  + abs (CircuitPlayground.motionZ());
  if(shake > shakeThresh) {
    CircuitPlayground.playTone(440, 200);
    blehid.keyPress('b');
  }

  //Works as the a key for the game by tilting the controller to the left
  if(CircuitPlayground.motionX() && xAxis >=.5) {
    blehid.keyPress('a');
    CircuitPlayground.setPixelColor(5, 105, 95, abs(xAxis)*5);
    //blehid.keyRelease();
    //delay(50);
  }
  else {
    blehid.keyRelease();
  }

  // Works as the d key for the game by tilting the controller to the right
  if(CircuitPlayground.motionX() && xAxis <=-.5) {
    blehid.keyPress('d');
    CircuitPlayground.setPixelColor(4, 105, 95, abs(xAxis)*5);
    //blehid.keyRelease();
    //delay(50);
  }
  else {
    blehid.keyRelease();
  }

 

  //This is for the potentiometer
  //When a value is reached/passed, it turns on some pixels for some "effect" and feedback
  //When the potentiometer is turned the z key is "pressed"
  value = analogRead(10);
  pixels = map(value, 0, 1023, 0, 10);

  CircuitPlayground.clearPixels();
  for (int p=0; p<pixels; p++) {
    CircuitPlayground.setPixelColor(p, 0xFF00FF);
    blehid.keyPress('z');
  }
  delay(100);

  //This is for the external light sensor
  //Detects how much light the external light sensor is getting
  //If the value is over 985 the q key is "pressed"
  int luminosity = analogRead(PHOTORESISTOR_PIN);
  Serial.println(luminosity);
  if(luminosity >= 985)
  {
    blehid.keyPress('q');
    delay(debounce);
    if(luminosity <= 970){
      blehid.keyRelease();
    }
  }

}

//This is for connection the controller via bluetooth
void startAdv(void)
{
  //Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

  //include BLE HID service
  Bluefruit.Advertising.addService(blehid);

  //There is enough room for the dev name in the advertising packet
  Bluefruit.Advertising.addName();

  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);
}

 


No comments:

Post a Comment

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