18 April 2021

Game Controller Project: Ooblets

Front

Back
 
Sides



    I chose to make a controller compatible with the game Ooblets. This controller is based off a deck of cards. The controller is the same length and width as a standard box of cards; however, it is deeper due to the space needed to fit the electrical components. The image on the front of the controller is hand painted as the controller was made out of wood. The image was based on scenery found in the game Ooblets. The reason it is prominently displayed on the front is because card boxes often display the artwork found on the backside of its contents on the outside of its packaging.

    The controller is mapped to the accelerometer’s x,y, and z axis. Essentially, change on the x-axis matching certain points on the z-axis will change which horizontal direction the player is taking, while y-axis compared to the z-axis will change the vertical direction. When the controller is shaken, the accelerometer takes its reading. If it is within a certain threshold, the accelerometer will press the escape key. Meanwhile, different pins are connected to the capacitive touch components on the CPE. A7 triggers the left arrow, A5 triggers the right arrow, A3 triggers the space bar, and A2 triggers the G key.

    There are several main signifiers to the controller. The user is able to tell which way to pick it up, as the image on the front of the box is of a landscape. The expectation is that users would pick up the controller the same way a user would pick up a picture or book. The pins on the side are just different enough from the rest of the controller that ideally a user would think to touch them and see what it might do. The mesh panelling on the back of the controller allows for some audible feedback when shaking the controller. It also acts as a signifier as there is better grip against your hand. You can quite literally hear if components are shaking enough to trigger the escape key.

    What are some ways I could have improved the feedback the controller gives without taking away from its original intent of resembling a card deck box?

Schematic
Video


Code

 /*                                                                                 

 * Written by Melissa Wells

 * DIG3602C Final Project

 */

 

#include <Adafruit_CircuitPlayground.h>

//#include <Adafruit_Circuit_Playground.h>


#include <Keyboard.h>

#include <Mouse.h>

#include <math.h>


#define TAP_THRESHOLD       10          // Tap detect threshold

#define ROLL_THRESHOLD      30          //roll detect threshold


//tap and shake variables

bool tapDetected;

int tapCount;

float shakeAccel;


const int debounce = 100;


//testing code for traditional keyboardinput

char input;


void setup() {

  // put your setup code here, to run once:

  Serial.begin(9600);

  while(!Serial);

  CircuitPlayground.begin(); 

  Keyboard.begin();

  Mouse.begin(); 



  Serial.begin(9600);

 

  CircuitPlayground.begin();

  //accelerometer range (2_g, 4_g, or 8_g)

  CircuitPlayground.setAccelRange(LIS3DH_RANGE_8_G);


/*  //tap range

  CircuitPlayground.setAccelTap(2, TAP_THRESHOLD);

   //  attachInterrupt(digitalPinToInterrupt(A2), tapCallback, FALLING);

  attachInterrupt(digitalPinToInterrupt(A2), tapCallback, CHANGE);

  tapDetected = false;

  tapCount = 0; */

}


void loop() {   

  // put your main code here, to run repeatedly:

 /* if (!CircuitPlayground.slideSwitch())

  {

    return;

  } */

  

  //read accelorometer x and y

  float x = CircuitPlayground.motionX();

  Serial.println("X: ");

  Serial.println(x);

  Serial.println("\t");


  float y = CircuitPlayground.motionX();

  Serial.println("Y: ");

  Serial.println(y);

  Serial.println("\t");


  float z = CircuitPlayground.motionX();

  Serial.println("Z: ");

  Serial.println(z);

  Serial.println("\t");    


  delay(1000);


  //Movement Code

  //X Axis

  //if move left

  //if (x > 1.0 && y <= z)

  if (x > 1.0 && z >= 5)

  {

    Keyboard.press('d');      

    //delay(debounce);

  }

  //if move right

  //if (x < -1.0 && y <= z)

  if (x < 1.0 && z <= -7)

  {

    Keyboard.press('a');

    //delay(debounce);

  } 

  //Y Axis

  //if move up

  //if (y > 1.0 && x <= z)

  if (y > 1.0 && z <= 3)

  {

    Keyboard.press('s');

    //delay(debounce);

  }

  //if move down

  //if (y < -1.0 && x <= z)

  if (y < -1.0 && z <= 1)

  {

    Keyboard.press('w');

    //delay(debounce);

  }

  //release keys

  if (x <= 1.0 && x >= -1.0)

  {

    Keyboard.release('a');

    Keyboard.release('d');

    delay(debounce);

  }

  if (y <= 1.0 && y >= -1.0)

  {

    Keyboard.release('s');

    Keyboard.release('w');

    delay(debounce);

  }


  //if shake

  shakeAccel = sqrt(x*x + y*y + z*z);

  if (shakeAccel > ROLL_THRESHOLD)

  {

    Serial.println("Shaking Bacon");

    Keyboard.press(177);

    delay(debounce);

    Keyboard.release(177);

  }  

  

  //call Tap code 

/*  CircuitPlayground.getAccelTap();

  if (tapDetected != false) {

    tapCount = tapCount + 1;

    Serial.println("TAP!");

    //hit spacebar

    if (tapCount == 1)

    {

      Keyboard.write(32);

      //delay(debounce); 

      //Keyboard.release(32);

    }

    if (tapCount == 2)

    {

      Keyboard.press('g');

      Keyboard.release('g');

    } 

    tapCount = 0;

    tapDetected = false; 

  } */


  //LEFT ARROW

 int threshold = 900;

  if (CircuitPlayground.readCap(A7) > threshold)

  {

    Serial.println("touched it");

    Keyboard.write(216);

  } 


  //RIGHT ARROW

  if (CircuitPlayground.readCap(A5) > threshold)

  {

    Serial.println("touched it");

    Keyboard.write(215);

  }  


  //G BUTTON

  if (CircuitPlayground.readCap(A3) > threshold)

  {

    Serial.println("touched it");

    Keyboard.write('g');

  }  


  //SPACE BUTTON

  if (CircuitPlayground.readCap(A2) > threshold)

  {

    Serial.println("touched it");

    Keyboard.write(' ');

  }  


}


void tapCallback() {

  tapDetected = true;

}

No comments:

Post a Comment

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