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 6:3be57cf4bd33, committed 2015-10-22
- Comitter:
- jford38
- Date:
- Thu Oct 22 08:02:28 2015 +0000
- Parent:
- 5:cfec780c935b
- Child:
- 7:9506f2d84162
- Commit message:
- Split game synchronization code into separate .h and .cpp files. Also renamed to "game_synchronizer.h" and "game_synchronizer.cpp"
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/game_synchronizer.cpp Thu Oct 22 08:02:28 2015 +0000 @@ -0,0 +1,187 @@ +#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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/game_synchronizer.h Thu Oct 22 08:02:28 2015 +0000 @@ -0,0 +1,93 @@ +#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 15 22:07:40 2015 +0000 +++ b/main.cpp Thu Oct 22 08:02:28 2015 +0000 @@ -1,37 +1,62 @@ -// THIS GUY LISTENS AND REPEATS. CLIENT. MASTER. -// (It doesn't make sense, I know.) +// Student Side. #include "mbed.h" -#include "two_player.h" +#include "game_synchronizer.h" + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); +DigitalIn pb_l(p24); // left button +DigitalIn pb_r(p21); // right button +DigitalIn pb_u(p22); // up button +DigitalIn pb_d(p23); // down button + +Game_Synchronizer sync(p9,p10,p11, PLAYER1); // (tx, rx, rst, player mode) -uLCD_2P uLCD(p28,p27,p26, PLAYER1); // serial tx, serial rx, reset pin; +// For debug only. Don't use in production code. It will slow your game down a lot. +Serial pc(USBTX, USBRX); - +void game_init(void) { + + led1 = 0; led2 = 0; led3 = 0; led4 = 0; + + pb_l.mode(PullUp); + pb_r.mode(PullUp); + pb_u.mode(PullUp); + pb_d.mode(PullUp); + + 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. + pc.printf("Initialized...\n"); // Let us know you finished initializing. +} + int main (void) { int* buttons; - - pc.printf("\033[2J\033[0;0H"); - pc.printf("I'm alive! Player 1\n"); - uLCD.init(); - pc.printf("Initialized...\n"); + game_init(); float theta = 0; while(1) { - uLCD.line(64,64,64+50*cos(theta),64+50*sin(theta), BLACK); + sync.line(64,64,64+50*cos(theta),64+50*sin(theta), BLACK); theta += 0.05; - uLCD.line(64,64,64+50*cos(theta),64+50*sin(theta), RED); - uLCD.circle(10,10,100, GREEN); - uLCD.filled_circle(4,4,10, 0xAB); - uLCD.triangle(10,10, 20,20, 20,40, 0xAB); - uLCD.rectangle(100,100, 90,90, GREEN); - uLCD.filled_rectangle(100,100, 110,110, 0xAB); - uLCD.pixel(40, 40, WHITE); + sync.line(64,64,64+50*cos(theta),64+50*sin(theta), RED); + sync.circle(10,10,100, GREEN); + sync.filled_circle(4,4,10, 0xAB); + sync.triangle(10,10, 20,20, 20,40, 0xAB); + sync.rectangle(100,100, 90,90, GREEN); + sync.filled_rectangle(100,100, 110,110, 0xAB); + sync.pixel(40, 40, WHITE); - uLCD.update(); - buttons = uLCD.get_button_state(); + sync.update(); + buttons = sync.get_button_state(); + led1 = buttons[0]; + led2 = buttons[1]; + led3 = buttons[2]; + led4 = buttons[3]; //pc.printf("Button State: %x %x %x %x %x\n", buttons[0], buttons[1], buttons[2], buttons[3], buttons[4]); //pc.printf("\033[2J\033[0;0H"); }
--- a/two_player.h Thu Oct 15 22:07:40 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -#ifndef TWO_PLAYER_H__ -#define TWO_PLAYER_H__ - -#include <cmath> -#include "uLCD_4DGL.h" -#include "EthernetInterface.h" - -#define PLAYER1 true -#define PLAYER2 false - -Serial pc(USBTX, USBRX); - -const char* PLAYER1_IP = "192.168.2.1"; -const char* PLAYER2_IP = "192.168.2.2"; -const int SERVER_PORT = 7; - -DigitalOut led(LED2); - - -class uLCD_2P -{ - -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 - }; - - uLCD_2P(PinName tx, PinName rx, PinName rst, bool player) { - p1_p2 = player; - LCD = new uLCD_4DGL (tx, rx, rst); - } - - void 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"); - //wait(1); - } - - 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 draw(int CMD) {_draw(CMD, 0,0,0,0,0,0,0, 0); } - void draw(int CMD, int a) { _draw(CMD, a, 0,0,0,0,0,0, 1); } - void draw(int CMD, int a, int b) { _draw(CMD, a, b, 0,0,0,0,0, 2); } - void draw(int CMD, int a, int b, int c) { _draw(CMD, a, b, c, 0,0,0,0, 3); } - void draw(int CMD, int a, int b, int c, int d) { _draw(CMD, a, b, c, d, 0,0,0, 4); } - void draw(int CMD, int a, int b, int c, int d, int e) { _draw(CMD, a, b, c, d, e, 0,0, 5); } - void 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 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 _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 background_color(int color) { draw(BG_COLOR_CMD, color); } - void line(int sx, int sy, int ex, int ey, int color) { draw(LINE_CMD, sx, sy, ex, ey, color); } - void circle(int x , int y , int radius, int color) { draw(CIRCLE_CMD, x, y, radius, color); } - void filled_circle(int x , int y , int radius, int color) { draw(FILLED_CIRCLE_CMD, x, y, radius, color); } - void 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 rectangle(int a, int b, int c, int d, int col) { draw(RECT_CMD, a, b, c, d, col); } - void filled_rectangle(int a, int b, int c, int d, int col) { draw(FILLED_RECT_CMD, a, b, c, d, col); } - void pixel(int a, int b, int col) { draw(PIX_CMD, a, b, col); } - void 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 read_pixel(int x, int y) { return LCD->read_pixel(x, y); } - - void 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* get_button_state() { - return buttons; - } - - void 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)); - } - - //pc.printf("Buffer: "); - /*for(int i=0; i<buffer_size; i++) { - pc.printf("%d ", buffer[i]); - i++; - } - pc.printf("\n"); - */ - 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; - } - } - } - - ~uLCD_2P() { - sock->close(); - eth->disconnect(); - delete sock; - delete server; - delete eth; - } - - //private: - bool master_slave; - - int buffer[1024]; - int buffer_idx; - - TCPSocketServer* server; - TCPSocketConnection* sock; - EthernetInterface* eth; - - uLCD_4DGL* LCD; - - int buttons[5]; -}; - -#endif \ No newline at end of file