Daniel Dakev / Mbed 2 deprecated laser-tag

Dependencies:   mbed 4DGL-uLCD-SE PinDetect SoftI2C

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