Revenge of the Mouse
Dependencies: 4DGL-uLCD-SE EthernetInterface Game_Synchronizer LCD_fonts MMA8452 SDFileSystem mbed-rtos mbed wave_player
Fork of 2035_Tanks_Shell by
Revision 7:9506f2d84162, committed 2015-10-22
- Comitter:
- jford38
- Date:
- Thu Oct 22 09:14:47 2015 +0000
- Parent:
- 6:3be57cf4bd33
- Child:
- 8:e6dd05393290
- Commit message:
- Now contains a switch for single vs. multiplayer modes. ; At the beginning of the game, the master must select the play mode.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game_Synchronizer/game_synchronizer.cpp Thu Oct 22 09:14:47 2015 +0000 @@ -0,0 +1,190 @@ +#include "game_synchronizer.h" + +extern Serial pc; + +Game_Synchronizer::Game_Synchronizer(PinName tx, PinName rx, PinName rst, bool player) { + p1_p2 = player; + LCD = new uLCD_4DGL (tx, rx, rst); +} + +void Game_Synchronizer::init(int mode) { + play_mode = mode; + buffer_idx = 0; + memset(buttons, 0, sizeof(buttons)); + + switch (p1_p2) { + case PLAYER1: // Client + + if(MULTI_PLAYER == play_mode) { + eth = new EthernetInterface(); + eth->init(PLAYER1_IP, "255.255.255.0", "0.0.0.0"); + eth->connect(); + + sock = new TCPSocketConnection(); + while(sock->connect(PLAYER2_IP, SERVER_PORT) < 0) { + //pc.printf("Trying to connect.\n"); + } + } + break; + case PLAYER2: // Server + eth = new EthernetInterface(); + eth->init(PLAYER2_IP, "255.255.255.0", "0.0.0.0"); + eth->connect(); + + server = new TCPSocketServer(); + server->bind(SERVER_PORT); + server->listen(); + sock = new TCPSocketConnection(); + server->accept(*sock); + sock->set_blocking(false, 1500); + break; + } +} + +// Yes, this sucks. If you're smart, find a good way to do variable args and show me! +// Look into template metaprogramming! + +void Game_Synchronizer::draw(int CMD) {_draw(CMD, 0,0,0,0,0,0,0, 0); } +void Game_Synchronizer::draw(int CMD, int a) { _draw(CMD, a, 0,0,0,0,0,0, 1); } +void Game_Synchronizer::draw(int CMD, int a, int b) { _draw(CMD, a, b, 0,0,0,0,0, 2); } +void Game_Synchronizer::draw(int CMD, int a, int b, int c) { _draw(CMD, a, b, c, 0,0,0,0, 3); } +void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d) { _draw(CMD, a, b, c, d, 0,0,0, 4); } +void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e) { _draw(CMD, a, b, c, d, e, 0,0, 5); } +void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e, int f) { _draw(CMD, a, b, c, d, e, f, 0, 6); } +void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e, int f, int g) { _draw(CMD, a, b, c, d, e, f, g, 7); } + +void Game_Synchronizer::_draw(int CMD, int a, int b, int c, int d, int e, int f, int g, char nArgs){ + + // Deal with overflows + // if(buffer_idx + nArgs > 256) {//flush();} + + if(nArgs > 7) { + //pc.printf("Error in call to _draw(): nArgs > 7 not allowed!\n"); + return; + } + + buffer[buffer_idx] = CMD; + if(nArgs >= 1) buffer[buffer_idx+1] = a; + if(nArgs >= 2) buffer[buffer_idx+2] = b; + if(nArgs >= 3) buffer[buffer_idx+3] = c; + if(nArgs >= 4) buffer[buffer_idx+4] = d; + if(nArgs >= 5) buffer[buffer_idx+5] = e; + if(nArgs >= 6) buffer[buffer_idx+6] = f; + if(nArgs >= 7) buffer[buffer_idx+7] = g; + // ERROR: nArgs > 7 + + + buffer_idx += nArgs+1; +} + + +void Game_Synchronizer::background_color(int color) { draw(BG_COLOR_CMD, color); } +void Game_Synchronizer::line(int sx, int sy, int ex, int ey, int color) { draw(LINE_CMD, sx, sy, ex, ey, color); } +void Game_Synchronizer::circle(int x , int y , int radius, int color) { draw(CIRCLE_CMD, x, y, radius, color); } +void Game_Synchronizer::filled_circle(int x , int y , int radius, int color) { draw(FILLED_CIRCLE_CMD, x, y, radius, color); } +void Game_Synchronizer::triangle(int a, int b, int c, int d , int e, int f, int col) { draw(TRI_CMD, a, b, c, d, e, f, col); } +void Game_Synchronizer::rectangle(int a, int b, int c, int d, int col) { draw(RECT_CMD, a, b, c, d, col); } +void Game_Synchronizer::filled_rectangle(int a, int b, int c, int d, int col) { draw(FILLED_RECT_CMD, a, b, c, d, col); } +void Game_Synchronizer::pixel(int a, int b, int col) { draw(PIX_CMD, a, b, col); } +void Game_Synchronizer::cls(void) { draw(CLS_CMD); } + +/*void BLIT(int x1, int y1, int x2, int y2, int *colors) { + int size = abs((x1-x2)*(y1-y2)); + // pad to a multiple of 4 and memset buffer... + // I'll get to it later. +}*/ + +// Reads don't need to be done on the slave side. Hopefully both sides match! +int Game_Synchronizer::read_pixel(int x, int y) { return LCD->read_pixel(x, y); } + +void Game_Synchronizer::set_button_state(int a, int b, int c, int d, int e) { + buttons[0] = a; buttons[1] = b; buttons[2] = c; + buttons[3] = d; buttons[4] = e; +} + +int* Game_Synchronizer::get_button_state() { + return buttons; +} + +void Game_Synchronizer::update() { + int buffer_size = buffer_idx; + buffer_idx = 0; + + if(p1_p2 == PLAYER1 && MULTI_PLAYER == play_mode) { + sock->set_blocking(true, 100); + sock->send_all((char*)buffer, (buffer_size+1)*sizeof(buffer[0])); + + int n = sock->receive((char*)buttons, sizeof(buttons)); + //if(n < 0) {pc.printf("RECEIVE ERROR.\n");} + + }else if(p1_p2 == PLAYER2) { + sock->set_blocking(true, 100); + int n = sock->receive((char*)buffer, sizeof(buffer)); + //if(n < 0) {pc.printf("RECEIVE ERROR.\n");} + buffer[n] = '\0'; + buffer_size = n/sizeof(buffer[0]) - 1; + + sock->send_all((char*)buttons, sizeof(buttons)); + } + + int idx = 0; + while(idx < buffer_size) { + char cmd = buffer[idx]; + idx++; + + switch(cmd) { + case CLS_CMD: + LCD->cls(); + //pc.printf("Clear the screen!\n"); + break; + case BG_COLOR_CMD: + LCD->background_color(buffer[idx+1]); + //pc.printf("Change the background to 0x%X\n", buffer[idx]); + idx += 1; + break; + case LINE_CMD: + //pc.printf("LINE: (%d, %d) - (%d, %d) COLOR: 0x%X\n", buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); + LCD->line(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); + idx += 5; + break; + case CIRCLE_CMD: + //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); + LCD->circle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3]); + idx += 4; + break; + case FILLED_CIRCLE_CMD: + //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); + LCD->filled_circle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3]); + idx += 4; + break; + case TRI_CMD: + //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); + LCD->triangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4], buffer[idx+5], buffer[idx+6]); + idx += 7; + break; + case RECT_CMD: + LCD->rectangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); + idx += 5; + break; + case FILLED_RECT_CMD: + LCD->filled_rectangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); + idx += 5; + break; + case PIX_CMD: + LCD->pixel(buffer[idx], buffer[idx+1], buffer[idx+2]); + idx += 3; + break; + default: + //pc.printf("UNKNOWN CMD %d: This could get ugly!\n", cmd); + idx += 0; + } + } +} + +Game_Synchronizer::~Game_Synchronizer() { + sock->close(); + eth->disconnect(); + delete sock; + delete server; + delete eth; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game_Synchronizer/game_synchronizer.h Thu Oct 22 09:14:47 2015 +0000 @@ -0,0 +1,96 @@ +#ifndef GAME_SYNC_H__ +#define GAME_SYNC_H__ + +#include <cmath> +#include "uLCD_4DGL.h" +#include "EthernetInterface.h" + +#define PLAYER1 true +#define PLAYER2 false + +#define SINGLE_PLAYER 0 +#define MULTI_PLAYER 1 + +#define PLAYER1_IP "192.168.2.1" +#define PLAYER2_IP "192.168.2.2" +#define SERVER_PORT 7 +#define ETH_PACKET_SIZE 1024 + + +class Game_Synchronizer +{ + +public : + + int p1_p2; + + enum Color + { + CLS_CMD, + BG_COLOR_CMD, + LINE_CMD, + CIRCLE_CMD, + FILLED_CIRCLE_CMD, + TRI_CMD, + RECT_CMD, + FILLED_RECT_CMD, + PIX_CMD + }; + + Game_Synchronizer(PinName tx, PinName rx, PinName rst, bool player); + + void init(int); + + // Yes, this sucks. If you're smart, find a good way to do variable args and show me! + // Look into template metaprogramming! + + void draw(int CMD); + void draw(int CMD, int a); + void draw(int CMD, int a, int b); + void draw(int CMD, int a, int b, int c); + void draw(int CMD, int a, int b, int c, int d); + void draw(int CMD, int a, int b, int c, int d, int e); + void draw(int CMD, int a, int b, int c, int d, int e, int f); + void draw(int CMD, int a, int b, int c, int d, int e, int f, int g); + void _draw(int CMD, int a, int b, int c, int d, int e, int f, int g, char nArgs); + + + void background_color(int color); + void line(int sx, int sy, int ex, int ey, int color); + void circle(int x , int y , int radius, int color); + void filled_circle(int x , int y , int radius, int color); + void triangle(int a, int b, int c, int d , int e, int f, int col); + void rectangle(int a, int b, int c, int d, int col); + void filled_rectangle(int a, int b, int c, int d, int col); + void pixel(int a, int b, int col); + void cls(void); + + //void BLIT(int x1, int y1, int x2, int y2, int *colors); // I'll get to this one later. + + // Reads don't need to be done on the slave side. Hopefully both sides match! + int read_pixel(int x, int y); + + void set_button_state(int a, int b, int c, int d, int e); + + int* get_button_state(); + + void update(void); + + ~Game_Synchronizer(); + + private: + + int play_mode; + int buffer[ETH_PACKET_SIZE]; + int buffer_idx; + + TCPSocketServer* server; + TCPSocketConnection* sock; + EthernetInterface* eth; + + uLCD_4DGL* LCD; + + int buttons[5]; +}; + +#endif \ No newline at end of file
--- a/game_synchronizer.cpp Thu Oct 22 08:02:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -#include "game_synchronizer.h" - -Game_Synchronizer::Game_Synchronizer(PinName tx, PinName rx, PinName rst, bool player) { - p1_p2 = player; - LCD = new uLCD_4DGL (tx, rx, rst); -} - -void Game_Synchronizer::init() { - - buffer_idx = 0; - memset(buttons, 0, sizeof(buttons)); - - switch (p1_p2) { - case PLAYER1: // Client - - eth = new EthernetInterface(); - eth->init(PLAYER1_IP, "255.255.255.0", "0.0.0.0"); - eth->connect(); - - sock = new TCPSocketConnection(); - while(sock->connect(PLAYER2_IP, SERVER_PORT) < 0) { - //pc.printf("Trying to connect.\n"); - } - - break; - case PLAYER2: // Server - eth = new EthernetInterface(); - eth->init(PLAYER2_IP, "255.255.255.0", "0.0.0.0"); - eth->connect(); - - server = new TCPSocketServer(); - server->bind(SERVER_PORT); - server->listen(); - sock = new TCPSocketConnection(); - server->accept(*sock); - sock->set_blocking(false, 1500); - break; - } - //pc.printf("Ethernet Connected.\n"); -} - -// Yes, this sucks. If you're smart, find a good way to do variable args and show me! -// Look into template metaprogramming! - -void Game_Synchronizer::draw(int CMD) {_draw(CMD, 0,0,0,0,0,0,0, 0); } -void Game_Synchronizer::draw(int CMD, int a) { _draw(CMD, a, 0,0,0,0,0,0, 1); } -void Game_Synchronizer::draw(int CMD, int a, int b) { _draw(CMD, a, b, 0,0,0,0,0, 2); } -void Game_Synchronizer::draw(int CMD, int a, int b, int c) { _draw(CMD, a, b, c, 0,0,0,0, 3); } -void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d) { _draw(CMD, a, b, c, d, 0,0,0, 4); } -void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e) { _draw(CMD, a, b, c, d, e, 0,0, 5); } -void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e, int f) { _draw(CMD, a, b, c, d, e, f, 0, 6); } -void Game_Synchronizer::draw(int CMD, int a, int b, int c, int d, int e, int f, int g) { _draw(CMD, a, b, c, d, e, f, g, 7); } - -void Game_Synchronizer::_draw(int CMD, int a, int b, int c, int d, int e, int f, int g, char nArgs){ - - // Deal with overflows - // if(buffer_idx + nArgs > 256) {//flush();} - - if(nArgs > 7) { - //pc.printf("Error in call to _draw(): nArgs > 7 not allowed!\n"); - return; - } - - buffer[buffer_idx] = CMD; - if(nArgs >= 1) buffer[buffer_idx+1] = a; - if(nArgs >= 2) buffer[buffer_idx+2] = b; - if(nArgs >= 3) buffer[buffer_idx+3] = c; - if(nArgs >= 4) buffer[buffer_idx+4] = d; - if(nArgs >= 5) buffer[buffer_idx+5] = e; - if(nArgs >= 6) buffer[buffer_idx+6] = f; - if(nArgs >= 7) buffer[buffer_idx+7] = g; - // ERROR: nArgs > 7 - - - buffer_idx += nArgs+1; -} - - -void Game_Synchronizer::background_color(int color) { draw(BG_COLOR_CMD, color); } -void Game_Synchronizer::line(int sx, int sy, int ex, int ey, int color) { draw(LINE_CMD, sx, sy, ex, ey, color); } -void Game_Synchronizer::circle(int x , int y , int radius, int color) { draw(CIRCLE_CMD, x, y, radius, color); } -void Game_Synchronizer::filled_circle(int x , int y , int radius, int color) { draw(FILLED_CIRCLE_CMD, x, y, radius, color); } -void Game_Synchronizer::triangle(int a, int b, int c, int d , int e, int f, int col) { draw(TRI_CMD, a, b, c, d, e, f, col); } -void Game_Synchronizer::rectangle(int a, int b, int c, int d, int col) { draw(RECT_CMD, a, b, c, d, col); } -void Game_Synchronizer::filled_rectangle(int a, int b, int c, int d, int col) { draw(FILLED_RECT_CMD, a, b, c, d, col); } -void Game_Synchronizer::pixel(int a, int b, int col) { draw(PIX_CMD, a, b, col); } -void Game_Synchronizer::cls(void) { draw(CLS_CMD); } - -/*void BLIT(int x1, int y1, int x2, int y2, int *colors) { - int size = abs((x1-x2)*(y1-y2)); - // pad to a multiple of 4 and memset buffer... - // I'll get to it later. -}*/ - -// Reads don't need to be done on the slave side. Hopefully both sides match! -int Game_Synchronizer::read_pixel(int x, int y) { return LCD->read_pixel(x, y); } - -void Game_Synchronizer::set_button_state(int a, int b, int c, int d, int e) { - buttons[0] = a; buttons[1] = b; buttons[2] = c; - buttons[3] = d; buttons[4] = e; -} - -int* Game_Synchronizer::get_button_state() { - return buttons; -} - -void Game_Synchronizer::update() { - int buffer_size; - sock->set_blocking(true, 100); - if(p1_p2 == PLAYER1) { - buffer_size = buffer_idx; - sock->send_all((char*)buffer, (buffer_size+1)*sizeof(buffer[0])); - buffer_idx = 0; - - int n = sock->receive((char*)buttons, sizeof(buttons)); - //if(n < 0) {pc.printf("RECEIVE ERROR.\n");} - - }else if(p1_p2 == PLAYER2) { - int n = sock->receive((char*)buffer, sizeof(buffer)); - //if(n < 0) {pc.printf("RECEIVE ERROR.\n");} - buffer[n] = '\0'; - buffer_size = n/sizeof(buffer[0]) - 1; - - sock->send_all((char*)buttons, sizeof(buttons)); - } - - int idx = 0; - while(idx < buffer_size) { - char cmd = buffer[idx]; - idx++; - - switch(cmd) { - case CLS_CMD: - LCD->cls(); - //pc.printf("Clear the screen!\n"); - break; - case BG_COLOR_CMD: - LCD->background_color(buffer[idx+1]); - //pc.printf("Change the background to 0x%X\n", buffer[idx]); - idx += 1; - break; - case LINE_CMD: - //pc.printf("LINE: (%d, %d) - (%d, %d) COLOR: 0x%X\n", buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); - LCD->line(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); - idx += 5; - break; - case CIRCLE_CMD: - //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); - LCD->circle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3]); - idx += 4; - break; - case FILLED_CIRCLE_CMD: - //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); - LCD->filled_circle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3]); - idx += 4; - break; - case TRI_CMD: - //pc.printf("CIRCLE: (%d, %d), r=%d\n", buffer[idx], buffer[idx+1], buffer[idx+2]); - LCD->triangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4], buffer[idx+5], buffer[idx+6]); - idx += 7; - break; - case RECT_CMD: - LCD->rectangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); - idx += 5; - break; - case FILLED_RECT_CMD: - LCD->filled_rectangle(buffer[idx], buffer[idx+1], buffer[idx+2], buffer[idx+3], buffer[idx+4]); - idx += 5; - break; - case PIX_CMD: - LCD->pixel(buffer[idx], buffer[idx+1], buffer[idx+2]); - idx += 3; - break; - default: - //pc.printf("UNKNOWN CMD %d: This could get ugly!\n", cmd); - idx += 0; - } - } -} - -Game_Synchronizer::~Game_Synchronizer() { - sock->close(); - eth->disconnect(); - delete sock; - delete server; - delete eth; -}
--- a/game_synchronizer.h Thu Oct 22 08:02:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -#ifndef GAME_SYNC_H__ -#define GAME_SYNC_H__ - -#include <cmath> -#include "uLCD_4DGL.h" -#include "EthernetInterface.h" - -#define PLAYER1 true -#define PLAYER2 false - -#define PLAYER1_IP "192.168.2.1" -#define PLAYER2_IP "192.168.2.2" -#define SERVER_PORT 7 -#define ETH_PACKET_SIZE 1024 - - -class Game_Synchronizer -{ - -public : - - int p1_p2; - - enum Color - { - CLS_CMD, - BG_COLOR_CMD, - LINE_CMD, - CIRCLE_CMD, - FILLED_CIRCLE_CMD, - TRI_CMD, - RECT_CMD, - FILLED_RECT_CMD, - PIX_CMD - }; - - Game_Synchronizer(PinName tx, PinName rx, PinName rst, bool player); - - void init(); - - // Yes, this sucks. If you're smart, find a good way to do variable args and show me! - // Look into template metaprogramming! - - void draw(int CMD); - void draw(int CMD, int a); - void draw(int CMD, int a, int b); - void draw(int CMD, int a, int b, int c); - void draw(int CMD, int a, int b, int c, int d); - void draw(int CMD, int a, int b, int c, int d, int e); - void draw(int CMD, int a, int b, int c, int d, int e, int f); - void draw(int CMD, int a, int b, int c, int d, int e, int f, int g); - void _draw(int CMD, int a, int b, int c, int d, int e, int f, int g, char nArgs); - - - void background_color(int color); - void line(int sx, int sy, int ex, int ey, int color); - void circle(int x , int y , int radius, int color); - void filled_circle(int x , int y , int radius, int color); - void triangle(int a, int b, int c, int d , int e, int f, int col); - void rectangle(int a, int b, int c, int d, int col); - void filled_rectangle(int a, int b, int c, int d, int col); - void pixel(int a, int b, int col); - void cls(void); - - //void BLIT(int x1, int y1, int x2, int y2, int *colors); // I'll get to this one later. - - // Reads don't need to be done on the slave side. Hopefully both sides match! - int read_pixel(int x, int y); - - void set_button_state(int a, int b, int c, int d, int e); - - int* get_button_state(); - - void update(void); - - ~Game_Synchronizer(); - - private: - bool master_slave; - - int buffer[ETH_PACKET_SIZE]; - int buffer_idx; - - TCPSocketServer* server; - TCPSocketConnection* sock; - EthernetInterface* eth; - - uLCD_4DGL* LCD; - - int buttons[5]; -}; - -#endif \ No newline at end of file
--- a/main.cpp Thu Oct 22 08:02:28 2015 +0000 +++ b/main.cpp Thu Oct 22 09:14:47 2015 +0000 @@ -18,6 +18,18 @@ // For debug only. Don't use in production code. It will slow your game down a lot. Serial pc(USBTX, USBRX); + +int game_menu(void) { + + // Figure out what mode the game will be run in. + // Right button -> Multiplayer + // Left button -> Single player + while(1) { + if(!pb_r) { wait(1); return MULTI_PLAYER; } // Delay to allow user time to stop pushing the button before the game starts! + if(!pb_l) { wait(1); return SINGLE_PLAYER; } // return whichever game mode the user selected. + } +} + void game_init(void) { led1 = 0; led2 = 0; led3 = 0; led4 = 0; @@ -29,7 +41,8 @@ pc.printf("\033[2J\033[0;0H"); // Clear the terminal screen. pc.printf("I'm alive! Player 1\n"); // Let us know you made it this far. - sync.init(); // Connect to the other player. + int mode = game_menu(); + sync.init(mode); // Connect to the other player. pc.printf("Initialized...\n"); // Let us know you finished initializing. } @@ -53,6 +66,7 @@ sync.update(); buttons = sync.get_button_state(); + led1 = buttons[0]; led2 = buttons[1]; led3 = buttons[2];