Laser tag guns code https://os.mbed.com/users/ddakev/notebook/laser-tag-system/
Dependencies: mbed 4DGL-uLCD-SE PinDetect SoftI2C
main.cpp
- Committer:
- ddakev
- Date:
- 2019-04-21
- Revision:
- 0:4c644bb83761
- Child:
- 1:7d957da791a5
File content as of revision 0:4c644bb83761:
#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; } } } }