19 April 2022

House Pusher (an HTML game) - Project Controller

 








Video: https://www.youtube.com/watch?v=0dxKIgr2ULo

I had to change my game multiple times since I ran into some technical issues (like ordering the wrong potentiometer, the photoresistor not working as planned, etc.) but then I decided last minute to settle with an HTML game that I found online called “House Pusher”. Its concept is from a puzzle video game genre called Sokoban in “which the player pushes crates or boxes around in a warehouse, trying to get them to storage locations” (Wikipedia.org).

It’s a simple puzzle game with multiple levels that only has 4 input controls (arrow keys: left, right, up, down) and the “r” button to restart the game. The main objective is to push tables onto a marked white spot in no specific order and after you put all the boxes in their appropriate spaces, the room becomes furnished, and you can then move on to the next level. I used the accelerometer to move the character so the character can therefore move along the grid via pushing the controller in any direction along the x or y-axis. I then decided to use the shake feature inside the Bluefruit which allows the player to restart the level.

I did not differentiate far from my original concept; I designed my controller to look like a table because of the game's basic theme; I also wanted to add some flair to it by adding a vase on top. I made the legs and vase out of polymer clay and then painted the box and clay parts with acrylic paint. To me, it looks more like an art piece than a controller, but it works when considering the setting of this game. Since the controller is essentially a box, with the CPB inside, I decided to make it Bluetooth for easier gameplay and then painted some signifying symbols so that any user that picks up the controller can have a general idea of how to use it. I wanted a way for the user to turn the controller on and off externally rather than having to open the box, but alas, I don’t have the proper tools to cut a small hole for the battery pack to be glued to the outside. But I think it works better visually to be hidden away and I believe most people would be curious enough to see if the front latch opens so they can see what rests inside; so I decided adding another symbol to display that would be futile.

My code is very simple. My threshold for the x and y-axis is 5 and -5 so the controls aren’t too sensitive nor too physically demanding on the user. I added a 500-millisecond delay so the character can move slow enough without racing across the screen and messing up the player’s progress. The shake threshold is at 20; I chose this number because I wanted to make sure the user doesn’t have to shake too hard or worry about their slight movements triggering the restart button. 

Question: If this game had 8 inputs (arrows, buttons c, x, z, and spacebar) like my previous game, how would you personally set this up on a CPB/CPE for efficient user usability? 

#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>
#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

//Initiate variables for shake threshold and accelerometer
int shakeThresh = 20;
float x, y, z;

void setup() {
// put your setup code here, to run once:
Bluefruit.begin();
Bluefruit.setTxPower(4);
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather 52");
bledis.begin();
//Start HID
blehid.begin();
//Start advertising device function
startAdv();

CircuitPlayground.begin();

}
//other setup

//Setting up slide switch pin
pinMode(CPLAY_SLIDESWITCHPIN, INPUT_PULLUP);

}

void loop() {
// put your main code here, to run repeatedly:

//Start of if statement that runs entire code. If slide switch is switched on and bluetooth is connected, run code.
if(digitalRead(CPLAY_SLIDESWITCHPIN)&& Bluefruit.connected()) {

//Declaring x,y,z to motion sensor
x = CircuitPlayground.motionX();
y = CircuitPlayground.motionY();
z = CircuitPlayground.motionZ();

//If x-axis is below -5, go left once, then release key. Delay then read next motion.
if (x < -5){
 uint8_t keycodes[6] = { HID_KEY_ARROW_LEFT, HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE };
 blehid.keyboardReport( 0 , keycodes );
 blehid.keyRelease();
 delay(500);

}

//If x-axis is above 5, go right once, then release key. Delay then read next motion.
if (x > 5){
 uint8_t keycodes[6] = { HID_KEY_ARROW_RIGHT, HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE };
 blehid.keyboardReport( 0 , keycodes );
 blehid.keyRelease();
 delay(500);

}

//if x-axis is between the ranges of -5 and 5, don't do anything.
else if (x < -5 && x > 5){
blehid.keyRelease();
}

//if y-axis is below -5. press down arrow key, then release. Delay until next motion.
if (y < -5){
 uint8_t keycodes[6] = { HID_KEY_ARROW_DOWN, HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE };
 blehid.keyboardReport( 0 , keycodes );
 blehid.keyRelease();
  delay(500);

}

//if y-axis is above 5, press up arrow key, then release. Delay until next motion.
if (y > 5){
 uint8_t keycodes[6] = { HID_KEY_ARROW_UP, HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE , HID_KEY_NONE };
 blehid.keyboardReport( 0 , keycodes );
 blehid.keyRelease();
 delay(500);

}

//if y-axis is between the ranges of -5 and 5, don't do anything.
if ( y < -5 && y > 5){
blehid.keyRelease();
}

//declare shake float and then assign the added absolute value of the x, y, and z-axis 
float shake = abs(CircuitPlayground.motionX())
+ abs(CircuitPlayground.motionY())
+ abs(CircuitPlayground.motionZ());

//if shake is above shake threshold (20), then press 'r' key and release.
if(shake > shakeThresh) {
blehid.keyPress('r');
blehid.keyRelease();
    }

  }

}
//End code






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.