Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed 4DGL-uLCD-SE PinDetect SoftI2C
Diff: main.cpp
- Revision:
- 0:4c644bb83761
- Child:
- 1:7d957da791a5
diff -r 000000000000 -r 4c644bb83761 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sun Apr 21 15:48:44 2019 +0000
@@ -0,0 +1,486 @@
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+#include "MMA8452.h"
+#include "PinDetect.h"
+#include "sfx.h"
+
+
+uLCD_4DGL uLCD(p9,p10,p11); // LCD (serial tx, serial rx, reset pin;)
+Serial pc(USBTX,USBRX);
+PinDetect trigger(p12, PullUp);
+Ticker acc_reader;
+Ticker reloader;
+Ticker reload_animation;
+Ticker countdown_ticker;
+Ticker timeRemaining_ticker;
+Ticker red_ticker, green_ticker;
+Timeout red_timeout, green_timeout;
+Timeout message_timeout;
+Timeout vibrator_timeout;
+MMA8452 acc(p6, p7, 100000);
+Serial xbee(p13, p14);
+DigitalOut rst1(p15);
+Serial IR(p28, p27);
+PwmOut IRLED(p21);
+AnalogOut speaker(p18);
+PwmOut vibrator(p24);
+DigitalOut greenLED(p22);
+DigitalOut redLED(p23);
+
+Ticker sound_ticker;
+unsigned char* sound_data;
+unsigned int num_elements = 0;
+int sound_i = 0;
+
+int xbeeId = -1;
+char playerName[11] = "N/A";
+bool waitingForId = false;
+int timeRemaining = 0;
+int countdown = 0;
+bool dead = false;
+
+const unsigned int MAX_BULLETS = 8;
+volatile unsigned int bullets;
+volatile bool reloading = false;
+
+enum GameState {NOT_STARTED, STARTING, RUNNING, ENDED};
+
+GameState gameState = NOT_STARTED;
+volatile unsigned int score = 0;
+
+void switchState(GameState newGameState);
+void shot_detected(int shooterId);
+
+
+void flash_red() {
+ redLED = !redLED;
+}
+
+void flash_green() {
+ greenLED = !greenLED;
+}
+
+void stop_red() {
+ redLED = 0;
+ red_ticker.detach();
+}
+
+void stop_green() {
+ greenLED = 0;
+ green_ticker.detach();
+}
+
+void play_sound() {
+ speaker = sound_data[sound_i] / 256.0f;
+ sound_i++;
+ if (sound_i>= num_elements) {
+ sound_i = 0;
+ //speaker = 0.0f;
+ sound_ticker.detach();
+ }
+}
+
+void clear_header() {
+ uLCD.filled_rectangle(0, 0, 128, 10, 0x000000);
+}
+
+void clear_middle() {
+ uLCD.filled_rectangle(0, 30, 128, 95, 0x000000);
+}
+
+void clear_footer() {
+ uLCD.filled_rectangle(0, 95, 128, 128, 0x000000);
+}
+
+void redraw_header() {
+ clear_header();
+ uLCD.color(GREEN);
+ uLCD.text_width(1);
+ uLCD.text_height(1);
+ uLCD.locate(0, 0);
+ uLCD.printf("%s", playerName);
+ uLCD.locate(13, 0);
+ int minutes = timeRemaining / 60;
+ int seconds = timeRemaining % 60;
+ uLCD.printf("%02d:%02d", minutes, seconds);
+}
+
+void redraw_score() {
+ clear_middle();
+ uLCD.color(GREEN);
+ uLCD.text_width(4);
+ uLCD.text_height(4);
+ uLCD.locate(1, 1);
+ uLCD.printf("%03d", score);
+}
+
+void redraw_middle_message(char* msg) {
+ clear_middle();
+ uLCD.color(GREEN);
+ uLCD.text_width(1);
+ uLCD.text_height(1);
+ uLCD.locate(0, 4);
+ uLCD.printf("%s", msg);
+}
+
+void redraw_footer_message(char* msg) {
+ clear_footer();
+ uLCD.color(GREEN);
+ uLCD.text_width(2);
+ uLCD.text_height(2);
+ uLCD.locate(0, 6);
+ uLCD.printf("%s", msg);
+}
+
+void redraw_bullets() {
+ clear_footer();
+ for(int i=0; i<bullets; i++) {
+ int offset = 6 * (i+1) + 9 * i;
+ uLCD.filled_rectangle(offset + 1, 95, offset + 8, 113, 0xFF0000);
+ uLCD.filled_rectangle(offset + 1, 113, offset + 8, 118, 0xFFDF00);
+ uLCD.filled_rectangle(offset, 118, offset + 9, 120, 0xFFDF00);
+ }
+}
+
+void draw_reload() {
+ if(gameState != RUNNING) {
+ reload_animation.detach();
+ return;
+ }
+ uLCD.text_width(3);
+ uLCD.text_height(3);
+ uLCD.locate(0, 4);
+ uLCD.color(RED);
+ uLCD.printf("RELOAD");
+ wait(0.25);
+ uLCD.locate(0, 4);
+ uLCD.color(WHITE);
+ uLCD.printf("RELOAD");
+}
+
+void redraw_countdown() {
+ clear_middle();
+ clear_footer();
+ uLCD.text_width(1);
+ uLCD.text_height(1);
+ uLCD.locate(7, 6);
+ uLCD.text_width(4);
+ uLCD.text_height(4);
+ uLCD.printf("%d", countdown);
+}
+
+void start_countdown() {
+ countdown --;
+ if(countdown == 0) {
+ // switch to running
+ countdown_ticker.detach();
+ switchState(RUNNING);
+ return;
+ }
+ redraw_countdown();
+}
+
+void start_tr_countdown() {
+ timeRemaining --;
+ redraw_header();
+ if(timeRemaining == 0) {
+ timeRemaining_ticker.detach();
+ switchState(ENDED);
+ return;
+ }
+}
+
+void turnOffVibrator() {
+ vibrator = 0.0;
+}
+
+void fire() {
+ if(gameState == NOT_STARTED && xbeeId == -1) {
+ waitingForId = true;
+ xbee.printf("%s", "nrj\n");
+ }
+ else if(gameState == RUNNING && !dead) {
+ if(bullets > 0) {
+ IR.putc('0'); // change to xbeeId
+ bullets--;
+ redraw_bullets();
+ sound_i = 0;
+ sound_data = Sounds::SHOT;
+ num_elements = SHOT_NUM_ELEMENTS;
+ sound_ticker.attach(&play_sound, 1.0 / SAMPLE_RATE);
+ vibrator = 0.7;
+ vibrator_timeout.attach(&turnOffVibrator, 0.5);
+ if(bullets == 0) {
+ draw_reload();
+ reload_animation.attach(&draw_reload, 0.5);
+ }
+ xbee.printf("gh%d\n", xbeeId);
+ }
+ else {
+ sound_i = 0;
+ sound_data = Sounds::OUT_OF_BULLETS;
+ num_elements = OUT_OF_BULLETS_NUM_ELEMENTS;
+ sound_ticker.attach(&play_sound, 1.0 / SAMPLE_RATE);
+ }
+ }
+}
+
+void reload() {
+ if(bullets < MAX_BULLETS) {
+ bullets ++;
+ if(bullets == 1) {
+ reload_animation.detach();
+ }
+ redraw_bullets();
+ sound_i = 0;
+ sound_data = Sounds::RELOADING;
+ num_elements = RELOADING_NUM_ELEMENTS;
+ sound_ticker.attach(&play_sound, 1.0 / SAMPLE_RATE);
+ }
+ else {
+ reloading = false;
+ reloader.detach();
+ sound_i = 0;
+ sound_data = Sounds::RELOAD_DONE;
+ num_elements = RELOAD_DONE_NUM_ELEMENTS;
+ sound_ticker.attach(&play_sound, 1.0 / SAMPLE_RATE);
+ }
+}
+
+void read_acc() {
+ double ax, ay, az;
+ acc.readXYZGravity(&ax, &ay, &az);
+ double acc = ax*ax + ay*ay + az*az;
+ double percent_y = ay * ay / acc;
+ if(percent_y > 0.56 && ay < 0 && reloading == false && bullets < MAX_BULLETS) {
+ pc.printf("RELOADING\r\n");
+ reloading = true;
+ reloader.attach(&reload, 0.5);
+ }
+ else if(!(percent_y > 0.56 && ay < 0) && reloading == true) {
+ reloading = false;
+ reloader.detach();
+ sound_i = 0;
+ sound_data = Sounds::RELOAD_DONE;
+ num_elements = RELOAD_DONE_NUM_ELEMENTS;
+ sound_ticker.attach(&play_sound, 1.0 / SAMPLE_RATE);
+ }
+}
+
+void readMessage(char* buffer) {
+ int len = 0;
+ while(1) {
+ if(xbee.readable()) {
+ char c = xbee.getc();
+ if(c == '\n') {
+ buffer[len++] = '\0';
+ return;
+ }
+ buffer[len++] = c;
+ }
+ if(IR.readable()) {
+ char c = IR.getc();
+ pc.putc(c);
+ if(c >= '0' && c <= '9') {
+ shot_detected(c - '0');
+ }
+ }
+ }
+}
+
+void shot_detected(int shooterId) {
+ if(!dead && shooterId != xbeeId) {
+ xbee.printf("gk%ds%d\n", shooterId, xbeeId);
+ }
+}
+
+void respawn() {
+ dead = false;
+ redraw_score();
+}
+
+void switchState(GameState newGameState) {
+ switch(newGameState) {
+ case NOT_STARTED:
+ gameState = NOT_STARTED;
+ redraw_header();
+ redraw_middle_message("Press the trigger to register device");
+ redraw_footer_message("Game Not Started");
+ break;
+ case STARTING:
+ gameState = STARTING;
+ countdown = 3;
+ redraw_countdown();
+ countdown_ticker.attach(&start_countdown, 1.0);
+ break;
+ case RUNNING:
+ gameState = RUNNING;
+ bullets = MAX_BULLETS;
+ score = 0;
+ redraw_score();
+ redraw_bullets();
+ timeRemaining_ticker.attach(&start_tr_countdown, 1.0);
+ greenLED = 1;
+ redLED = 0;
+ green_ticker.attach(&flash_green, 0.1);
+ red_ticker.attach(&flash_red, 0.1);
+ green_timeout.attach(&stop_green, 1.0);
+ red_timeout.attach(&stop_red, 1.0);
+ vibrator = 1;
+ vibrator_timeout.attach(&turnOffVibrator, 1.0);
+ break;
+ case ENDED:
+ gameState = ENDED;
+ clear_footer();
+ redraw_middle_message("Game Ended");
+ greenLED = 1;
+ redLED = 0;
+ green_ticker.attach(&flash_green, 0.1);
+ red_ticker.attach(&flash_red, 0.1);
+ green_timeout.attach(&stop_green, 1.0);
+ red_timeout.attach(&stop_red, 1.0);
+ vibrator = 1;
+ vibrator_timeout.attach(&turnOffVibrator, 1.0);
+ break;
+ default: break;
+ }
+}
+
+int main() {
+ uLCD.baudrate(3000000);
+ pc.baud(9600);
+ xbee.baud(9600);
+ trigger.attach_deasserted(&fire);
+ trigger.setSampleFrequency();
+ acc_reader.attach(&read_acc, 0.05);
+ rst1 = 0; //Set reset pin to 0
+ wait_ms(1);//Wait at least one millisecond
+ rst1 = 1;//Set reset pin to 1
+ wait_ms(1);//Wait another millisecond
+ IRLED.period(1.0/38000.0);
+ IRLED = 0.5;
+ IR.baud(2400);
+
+ redraw_header();
+
+ switchState(NOT_STARTED);
+
+ while(1) {
+ char msg[255];
+ readMessage(msg);
+ printf("%s\r\n", msg);
+ if(msg[0] == 'n') {
+ // action in not started
+ if(gameState != NOT_STARTED) continue;
+ if(msg[1] == 'i') {
+ // receiving id
+ if(waitingForId) {
+ xbeeId = msg[2] - '0';
+ pc.printf("ID: %d\n", xbeeId);
+ waitingForId = false;
+ }
+ }
+ else if(msg[1] == 'n') {
+ // receiving name
+ if(msg[2] - '0' == xbeeId) {
+ // changing name of current gun
+ char name[11];
+ int index = 0;
+ int msgIndex = 3;
+ while(msg[msgIndex] != '\0') {
+ if(index < 10) {
+ name[index++] = msg[msgIndex];
+ }
+ msgIndex++;
+ }
+ name[index] = '\0';
+ strcpy(playerName, name);
+ pc.printf("Name: %s\n", name);
+ redraw_header();
+ }
+ }
+ }
+ if(msg[0] == 'g') {
+ // game action
+ if(msg[1] == 's') {
+ // game start initiated
+ if(xbeeId != -1) {
+ int duration = 0;
+ int index = 2;
+ while(msg[index] != '\0') {
+ duration = duration * 10 + (msg[index++] - '0');
+ }
+ timeRemaining = duration;
+ redraw_header();
+ switchState(STARTING);
+ }
+ }
+ if(msg[1] == 'e') {
+ // game ended
+ if(xbeeId != -1) {
+ switchState(ENDED);
+ }
+ }
+ if(msg[1] == 'i') {
+ // kill info from server
+ if(xbeeId != -1) {
+ int shooterId = msg[2] - '0';
+ int index = 3;
+ char shooterName[11];
+ int nameIndex = 0;
+ while(msg[index] < '0' || msg[index] > '9') {
+ if(nameIndex < 10) {
+ shooterName[nameIndex++] = msg[index];
+ }
+ index++;
+ }
+ shooterName[nameIndex] = '\0';
+ int shooteeId = msg[index++] - '0';
+ char shooteeName[11];
+ nameIndex = 0;
+ while(msg[index] != '\0') {
+ if(nameIndex < 10) {
+ shooteeName[nameIndex++] = msg[index];
+ }
+ index++;
+ }
+ if(shooterId == xbeeId) {
+ char msg[80];
+ strcpy(msg, "You shot ");
+ strcat(msg, shooteeName);
+ strcat(msg, "!");
+ redraw_middle_message(msg);
+ score += 200;
+ message_timeout.attach(&redraw_score, 3.0);
+ green_ticker.attach(&flash_green, 0.05);
+ green_timeout.attach(&stop_green, 3.0);
+ vibrator = 1;
+ vibrator_timeout.attach(&turnOffVibrator, 1.0);
+ }
+ else if(shooteeId == xbeeId) {
+ char msg[80];
+ strcpy(msg, shooterName);
+ strcat(msg, " shot you!");
+ redraw_middle_message(msg);
+ dead = true;
+ if(score < 100) score = 0;
+ else score -= 100;
+ message_timeout.attach(&respawn, 5.0);
+ red_ticker.attach(&flash_red, 0.05);
+ red_timeout.attach(&stop_red, 5.0);
+ vibrator = 1;
+ vibrator_timeout.attach(&turnOffVibrator, 5.0);
+ }
+ }
+ }
+ if(msg[1] == 'r') {
+ xbeeId = -1;
+ strcpy(playerName, "N/A");
+ waitingForId = false;
+ dead = false;
+ switchState(NOT_STARTED);
+ score = 0;
+ }
+ }
+ }
+}
\ No newline at end of file