Game for 4180 Lab4
Dependencies: 4DGL-uLCD-SE 4180_lab4_tank_war_game Game_Synchronizer MMA8452 SDFileSystem mbed-rtos mbed wave_player
Dependents: 4180_lab4_tank_war_game
Diff: main.cpp
- Revision:
- 0:ffed9a3bc797
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Mar 13 21:23:17 2017 +0000 @@ -0,0 +1,434 @@ +// Student Side. + +#include "mbed.h" + +#include "SDFileSystem.h" +#include "wave_player.h" +#include "game_synchronizer.h" +#include "tank.h" +#include "bullet.h" +#include "globals.h" +#include "playSound.h" + + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + +DigitalIn pb_u(p21); // Up Button +DigitalIn pb_r(p22); // Right Button +DigitalIn pb_d(p23); // Down Button +DigitalIn pb_l(p24); // Left Button + +Serial pc(USBTX, USBRX); // Serial connection to PC. Useful for debugging! +MMA8452 acc(p9, p10, 100000); // Accelerometer (SDA, SCL, Baudrate) +uLCD_4DGL uLCD(p28,p27,p29); // LCD (tx, rx, reset) +SDFileSystem sd(p5, p6, p7, p8, "sd"); // SD (mosi, miso, sck, cs) +AnalogOut DACout(p18); // speaker +wave_player player(&DACout); // wav player +Game_Synchronizer sync(PLAYER1); // Game_Synchronizer (PLAYER) +Timer frame_timer; // Timer + +// Global variables go here. + +int winner = -1; +int whose_turn = PLAYER1; +int p1score = 0; +int p2score = 0; +int skyChange = 0; +int SKY_COLOR = 0x7EC0EE; +int SKY_COLOR2 = 0x0033cc; + + +// Ask the user whether to run the game in Single- or Multi-Player mode. +// Note that this function uses uLCD instead of sync because it is only +// writing to the local (Player1) lcd. Sync hasn't been initialized yet, +// so you can't use it anyway. For the same reason, you must access +// the buttons directly e.g. if( !pb_r ) { do something; }. + +// return MULTI_PLAYER if the user selects multi-player. +// return SINGLE_PLAYER if the user selects single-player. + +FILE *wave_file; +int game_menu(void) { + uLCD.baudrate(BAUD_3000000); + + // the locate command tells the screen where to place the text. + uLCD.cls(); + uLCD.locate(2,2); + uLCD.puts("Press Left for"); + uLCD.locate(2,3); + uLCD.puts("Single Player"); + uLCD.locate(2,5); + uLCD.puts("Press Right for"); + uLCD.locate(2,6); + uLCD.puts("Multi-Player"); + + // Button Example: + // Use !pb_r to access the player1 right button value. + // Eventually you should return SINGLE_PLAYER or MULTI_PLAYER + // depending on the user's choice. + + while(true) { + if (!pb_l) { + uLCD.cls(); + uLCD.locate(2,2); + uLCD.puts("Press Up"); + uLCD.locate(2,3); + uLCD.puts("For nighttime."); + uLCD.locate(2,5); + uLCD.puts("Press Down"); + uLCD.locate(2,6); + uLCD.puts("For daytime."); + while(true) { + if (!pb_u) { + skyChange = 1; + SKY_COLOR = SKY_COLOR2; + return SINGLE_PLAYER; + } + if (!pb_d) { + return SINGLE_PLAYER; + } + } + } + if (!pb_r) { + uLCD.cls(); + uLCD.locate(2,2); + uLCD.puts("Press Up"); + uLCD.locate(2,3); + uLCD.puts("For nighttime."); + uLCD.locate(2,5); + uLCD.puts("Press Down"); + uLCD.locate(2,6); + uLCD.puts("For daytime."); + while(true) { + if (!pb_u) { + skyChange = 1; + SKY_COLOR = SKY_COLOR2; + return MULTI_PLAYER; + } + if (!pb_d) { + return MULTI_PLAYER; + } + } + } + } +} + +// Initialize the world map. I've provided a basic map here, +// but as part of the assignment you must create more +// interesting map(s). +// Note that calls to sync.function() will run function() +// on both players' LCDs (assuming you are in multiplayer mode). +// In single player mode, only your lcd will be modified. (Makes sense, right?) +void map_init() { + + // Fill the entire screen with sky blue. + sync.background_color(SKY_COLOR); + + // Call the clear screen function to force the LCD to redraw the screen + // with the new background color. + sync.cls(); + + // Draw the ground in green. + sync.filled_rectangle(0,0,128,20, GND_COLOR); + + // Draw some obstacles. They don't have to be black, + // but they shouldn't be the same color as the sky or your tanks. + // Get creative here. You could use brown and grey to draw a mountain + // or something cool like that. + + sync.filled_rectangle(40, 40, 45, 90, AQUA); + sync.filled_rectangle(50, 30, 55, 70, PURPLE); + sync.filled_rectangle(59, 20, 69, 60, BLACK); + sync.filled_rectangle(74, 30, 79, 70, PURPLE); + sync.filled_rectangle(84, 40, 89, 90, AQUA); + + // Before you write text on the screens, tell the LCD where to put it. + sync.locate(0,15); + + // Set the text background color to match the sky. Just for looks. + sync.textbackground_color(SKY_COLOR); + + // Display the game title. + char title[] = " Tanks"; + sync.puts(title, sizeof(title)); + + // Flush the draw buffer and execute all the accumulated draw commands. + sync.update(); +} + +// Initialize the game hardware. +// Call game_menu to find out which mode to play the game in (Single- or Multi-Player) +// Initialize the game synchronizer. +void game_init(void) { + + led1 = 0; led2 = 0; led3 = 0; led4 = 0; + + pb_u.mode(PullUp); + pb_r.mode(PullUp); + pb_d.mode(PullUp); + pb_l.mode(PullUp); + + int mode = game_menu(); + sync.init(&uLCD, &acc, &pb_u, &pb_r, &pb_d, &pb_l, mode); // Connect to the other player. + map_init(); +} + +// Display some kind of game over screen which lets us know who won. +// Play a cool sound! +int game_over() { + int i = 0; + playSound("/sd/wavfiles/cheering.wav"); + + // score keeping + char* toPrint1 = new char [7]; + char* toPrint2 = new char [7]; + toPrint1[6] = '\0'; + toPrint2[6] = '\0'; + sprintf(&toPrint1[0], "P1: %d", p1score); + sprintf(&toPrint2[0], "P2: %d", p2score); + + while(1) { + sync.cls(); + // animated winning screen + sync.locate(i + 2, 10); + if (winner == PLAYER1) { + sync.puts("P1 WINS!\n", sizeof("P1 WINS!\n")); + } else if (winner == PLAYER2) { + sync.puts("P2 WINS!\n", sizeof("P2 WINS!\n")); + } + sync.locate(2, 8); + sync.puts(toPrint1, 8); + sync.locate(9, 8); + sync.puts(toPrint2, 8); + sync.locate(2, 6); + sync.puts("Press up to\n", sizeof("Press up to\n")); + sync.locate(2, 5); + sync.puts("continue!\n", sizeof("continue!\n")); + sync.update(); + (++i) %= 7; + wait(0.1); + // restart the game if up is pressed + if (!pb_u) { + return 1; + } + } +} + +void menuSound(void const *argument) +{ + FILE *wf; + wf=fopen("/sd/wavfiles/applause.wav","r"); + player.play(wf); + fclose(wf); +} + + +int main (void) { + int* p1_buttons; + int* p2_buttons; + + float ax1, ay1, az1; + float ax2, ay2, az2; + + // play menu sound + Thread thread1(menuSound); + game_init(); + + int restart = 1; + while (restart == 1) { + map_init(); + + // Create your tanks. + Tank t1(4, 21, 12, 8, TANK_RED); // (min_x, min_y, width, height, color) + Tank t2(111, 21, 12, 8, TANK_BLUE); // (min_x, min_y, width, height, color) + + // For each tank, create a bullet. + Bullet b1(&t1); + Bullet b2(&t2); + + // change skycolor + t1.changeSky(SKY_COLOR); + t2.changeSky(SKY_COLOR); + b1.changeSky(SKY_COLOR); + b2.changeSky(SKY_COLOR); + + // reset these values at the start of every round + restart = 0; + whose_turn = PLAYER1; + frame_timer.start(); + + // Your code starts here... + while(true) { + + // Get a pointer to the buttons for both sides. + // From now on, you can access the buttons for player x using + // + // px_buttons[U_BUTTON] + // px_buttons[R_BUTTON] + // px_buttons[D_BUTTON] + // px_buttons[L_BUTTON] + + p1_buttons = sync.get_p1_buttons(); + p2_buttons = sync.get_p2_buttons(); + + led1 = p1_buttons[0] ^ p2_buttons[0]; + led2 = p1_buttons[1] ^ p2_buttons[1]; + led3 = p1_buttons[2] ^ p2_buttons[2]; + led4 = p1_buttons[3] ^ p2_buttons[3]; + + // Get the accelerometer values. + sync.get_p1_accel_data(&ax1, &ay1, &az1); + sync.get_p2_accel_data(&ax2, &ay2, &az2); + + if(whose_turn == PLAYER1) { + + // delete old triangle on the other player + sync.triangle(118, 120, 118, 125, 123, 120, SKY_COLOR); + // triangle above player's turn + sync.triangle(5, 120, 5, 125, 10, 120, GREEN); + sync.update(); + + // Accelerometer + if(ax1 > ACC_THRESHOLD) { + // left + t1.reposition(-1, 0, 0); + } else if(ax1 < -1 * ACC_THRESHOLD) { + //right + t1.reposition(+1, 0, 0); + } + if(ay1 > ACC_THRESHOLD) { + // up + t1.reposition(0, 0, +1); + } else if(ay1 < -1 * ACC_THRESHOLD) { + // down + t1.reposition(0, 0, -1); + } + + // power up button + if(p1_buttons[U_BUTTON]) { + b1.powerUp(); + } + // shoot button + if(p1_buttons[D_BUTTON]) { + b1.shoot(); + } + + float dt = frame_timer.read(); + int intersection_code = b1.time_step(dt); + + // If you shot yourself, you lost. + if(sync.pixel_eq(intersection_code, t1.tank_color)) { + sync.update(); // Is this necessary? + winner = PLAYER2; + p2score = p2score + 1; + break; + } + // If you shot the other guy, you won! + if(sync.pixel_eq(intersection_code, t2.tank_color)) { + sync.update(); + winner = PLAYER1; + p1score = p1score + 1; + break; + } + // keep playing + if(intersection_code != BULLET_NO_COLLISION || intersection_code == BULLET_OFF_SCREEN) { + whose_turn = PLAYER2; + } + } else if(whose_turn == PLAYER2) { + // I gave you a lot of the logic for Player1. It's up to you to figure out Player2! + // If you are in SINGLE_PLAYER mode, you should use the p1 inputs to control p2. + // In MULTI_PLAYER mode, you should use the p2 inputs to control p2. + // + // Hint: + // sync.play_mode will tell you if you are in MULTI_PLAYER or SINGLE_PLAYER mode. + // + + // deletes triangle above other player + sync.triangle(5, 120, 5, 125, 10, 120, SKY_COLOR); + // triangle above player's turn + sync.triangle(118, 120, 118, 125, 123, 120, GREEN); + sync.update(); + + if (sync.play_mode == SINGLE_PLAYER) { + + if(ax1 > ACC_THRESHOLD) { + // left + t2.reposition(-1, 0, 0); + } else if(ax1 < -1 * ACC_THRESHOLD) { + //right + t2.reposition(+1, 0, 0); + } + if(ay1 > ACC_THRESHOLD) { + // up + t2.reposition(0, 0, +1); + } else if(ay1 < -1 * ACC_THRESHOLD) { + // down + t2.reposition(0, 0, -1); + } + + // powerup button + if(p1_buttons[U_BUTTON]) { + b2.powerUp(); + } + // shoot button + if(p1_buttons[D_BUTTON]) { + b2.shoot(); + } + } else if (sync.play_mode == MULTI_PLAYER) { + if(ax2 > ACC_THRESHOLD) { + // left + t2.reposition(+1, 0, 0); + } else if(ax2 < -1 * ACC_THRESHOLD) { + //right + t2.reposition(-1, 0, 0); + } + if(ay2 > ACC_THRESHOLD) { + // up + t2.reposition(0, 0, +1); + } else if(ay2 < -1 * ACC_THRESHOLD) { + // down + t2.reposition(0, 0, -1); + } + + // powerup button + if(p2_buttons[U_BUTTON]) { + b2.powerUp(); + } + // shoot button + if(p2_buttons[D_BUTTON]) { + b2.shoot(); + } + } + + float dt = frame_timer.read(); + int intersection_code = b2.time_step(dt); + + // If you shot yourself, you lost. + if(sync.pixel_eq(intersection_code, t2.tank_color)) { + sync.update(); // Is this necessary? + winner = PLAYER1; + p1score = p1score + 1; + break; + } + // If you shot the other guy, you won! + if(sync.pixel_eq(intersection_code, t1.tank_color)) { + sync.update(); + winner = PLAYER2; + p2score = p2score + 1; + break; + } + // keep playing + if(intersection_code != BULLET_NO_COLLISION || intersection_code == BULLET_OFF_SCREEN) { + whose_turn = PLAYER1; + } + } + + frame_timer.reset(); + sync.update(); + } + restart = game_over(); + } +} \ No newline at end of file