ECE 2035 AgarIO MiniProject
Dependencies: 4DGL-uLCD-SE ECE2035_Agar_Shell EthernetInterface Game_Synchronizer MMA8452 SDFileSystem Sound USBDevice mbed-rtos mbed wave_player
Fork of ECE2035_Agar_Shell by
This program is a MiniProject given in ECE 2035. This is to design and program the multiplayer ethernet based AGAR.IO mbed game. Starting code is given by the instructor to aid student to complete the project. It utilize uLCD, Accelerometer, pushbuttons, sdFileSystem, ethernetBreakoutBoard, speaker in mBED LPC1768. It uses the similar concept to the Game http://agar.io/
main.cpp
- Committer:
- pkoirala3
- Date:
- 2017-03-18
- Revision:
- 1:e487713a5231
- Parent:
- 0:9d6ea88b6d14
File content as of revision 1:e487713a5231:
// Student Side Shell Code // By: Prana Koirala // ECE 2035 // AGAR.GT Game // For the baseline, anywhere you see ***, you have code to write. #include "mbed.h" #include "SDFileSystem.h" #include "wave_player.h" #include "game_synchronizer.h" #include "misc.h" #include "blob.h" #include "playSound.h" #include "uLCD_4DGL.h" #include "TMP36.h" #define NUM_BLOBS 22 DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); DigitalOut RedLED(p15); DigitalOut GreenLED(p14); DigitalOut BlueLED(p13); DigitalIn pb_u(p21); // Up Button DigitalIn pb_r(p22); // Right Button DigitalIn pb_d(p23); // Down Button DigitalIn pb_l(p24); // Left Button TMP36 TEMP(p15); char hitTune[] = "/sd/score.wav"; // identifies a blob being eaten Serial pc(USBTX, USBRX); // Serial connection to PC. Useful for debugging! MMA8452 acc(p28, p27, 100000); // Accelerometer (SDA, SCL, Baudrate) uLCD_4DGL uLCD(p9,p10,p11); // 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 GSYNC game_synchronizer; // Game_Synchronizer GSYNC* sync = &game_synchronizer; // Timer frame_timer; // Timer int score1 = 0; // Player 1's score. int score2 = 0; // Player 2's score. int num_player = 0; int const time_unit = 1000; // time for screen refresh void display_Temp(void) { float V = TEMP; // Displaying Temp of chip so that player can quit game and cool it. uLCD.printf("\n\n\n\n\n\n\n\nTemp:%4.1F Deg F\n",V); } // This Display the game menu on the player 1 mbed to give option to play in single or multiplayer mode. // They can use up and down button to make choice, some sound effect added. int game_menu(void) { uLCD.set_font(FONT_8X12); uLCD.background_color(BGRD_COL); uLCD.textbackground_color(BGRD_COL); uLCD.cls(); uLCD.locate(0,0); uLCD.puts("Welcome to Agar"); uLCD.printf("\n\n"); wait(2.0); uLCD.printf("Loading Game..."); uLCD.printf("\n\n\n\n\n\n"); wait(3.0); display_Temp(); BlueLED = 1; uLCD.cls(); // Print single player or multiplayer mode. Depending which button is pressed, return either SINGLE_PLAYER or MULTI_PLAYER. uLCD.set_font(FONT_7X8); uLCD.printf("Select Mode:\n\n"); uLCD.printf("1P:Press up btn\n\n"); uLCD.printf("2P:Press down btn\n"); display_Temp(); int Mode = 0; while(1) { if(!pb_u) { Mode = SINGLE_PLAYER; break; } if(!pb_d) { Mode = MULTI_PLAYER; break; } } return Mode; } // Initialize the game hardware. // Call game_menu to find out which mode to play the game in (Single or MultiPlayer) // 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); 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 // game_menu MUST return either SINGLE_PLAYER or MULTI_PLAYER int num_player = game_menu(); GS_init(sync, &uLCD, &acc, &pb_u, &pb_r, &pb_d, &pb_l, num_player, PLAYER1); // Connect to the other player. pc.printf("Initialized...\n"); // Let us know you finished initializing. srand(time(NULL)); // Seed the random number generator. GS_cls(sync, SCREEN_BOTH); GS_update(sync); } // Function for displaying the string void prints_string(char* text, int x, int y, int backgrnd, int foregrnd, bool clr) { uLCD.background_color(backgrnd); uLCD.textbackground_color(foregrnd); uLCD.set_font(FONT_7X8); if (clr == 1) { uLCD.cls(); } uLCD.locate(x,y); uLCD.puts(text); uLCD.printf("\n\n\n\n\n\n"); display_Temp(); } // Display who won! int game_over(int winner) { if (winner == WINNER_P1) { // P1 wins char P1_WIN[10] = "P1 Won"; prints_string(P1_WIN, 0, 0, BGRD_COL, RED, 0); char buzzer[] = "/sd/won.wav"; playSound(buzzer); // Play the sound in the board } else if (winner == WINNER_P2) { // P2 OR AI wins if (num_player == SINGLE_PLAYER) { // AI wins char AI_WIN[10] = "PC Won"; prints_string(AI_WIN, 0, 0, BGRD_COL, RED, 0); char buzzer[] = "/sd/won.wav"; playSound(buzzer); // Play the sound in the board } else { // P2 wins char P2_WIN[10] = "P2 Won"; prints_string(P2_WIN, 0, 0, BGRD_COL, RED, 0); char buzzer[] = "/sd/won.wav"; playSound(buzzer); // Play the sound in the board } } else if (winner == WINNER_TIE) { // Tied game char NO_WIN[10] = "TIE"; prints_string(NO_WIN, 0, 0, BGRD_COL, RED, 0); char buzzer[] = "/sd/won.wav"; playSound(buzzer); // Play the sound in the board } while(1) { RedLED = 0; wait(0.75); RedLED = 1; if(!pb_r) { uLCD.printf("Loading new Game"); wait(1.5); uLCD.cls(); uLCD.printf("\n\n\n\n\n\n\n\n\n"); display_Temp(); return(1); } } } // Take in a pointer to the blobs array. Iterate over the array // and initialize each blob with BLOB_init(). Set the first blob to (for example) blue // and the second blob to (for example) red. Set the color(s) of the food blobs however you like. // Make the radius of the "player blobs" equal and larger than the radius of the "food blobs". void generate_blobs(BLOB* blobs) { int sizePlayer = 15; int sizeFood = 8; for (int i = 0; i < NUM_BLOBS; i++) { int rad = (i == PLAYER1 || i == PLAYER2) ? sizePlayer : sizeFood; // get the radius int col = (i == PLAYER1 || i == PLAYER2) ? ((i == PLAYER1) ? P1_COL : P2_COL) : FOOD_COL; // get the color BLOB_init(&blobs[i], rad, col); //void BLOB_init(BLOB* b, int rad, int color) BLOB_print(blobs[i]); } } int main (void) { Play_again: // Option to play again int score1 = 0; // Player 1's score reseting int score2 = 0; // Player 2's score reseting int* p1_buttons; int* p2_buttons; float ax1, ay1, az1; float ax2, ay2, az2; float time_step = .01; int rect_bl_x, rect_bl_y, rect_ur_x, rect_ur_y; // rect. boundary, bottom-left, top-right (x,y) float blob_x, blob_y; // pos (x,y) for a blob // Ask the user to choose (via pushbuttons) // to play in single- or multi-player mode. // Use their choice to correctly initialize the game synchronizer. game_init(); // Keep an array of blobs. Use blob 0 for player 1 and // blob 1 for player 2. BLOB blobs[NUM_BLOBS]; // Pass in a pointer to the blobs array. Iterate over the array // and initialize each blob with BLOB_init(). Set the radii and colors // anyway you see fit. generate_blobs(blobs); while(true) { GS_background_color(sync, SCREEN_BOTH, BGRD_COL); // paint background colors // In single-player, check to see if the player has eaten all other blobs. // In multi-player mode, check to see if the players have tied by eating half the food each. // *** // check based on food eaten if ((score1 + score2) >= (NUM_BLOBS-2) ) { if (score1 > score2 && blobs[PLAYER1].valid == 1) { // P1 wins game_over(WINNER_P1); game_over(WINNER_P1); goto Play_again; // To play again } else if (score2 > score1 && blobs[PLAYER2].valid == 1) { //P2 || AI wins game_over(WINNER_P2); game_over(WINNER_P1); goto Play_again; // To play again } else if (score1 == score2) { // Tie game game_over(WINNER_TIE); game_over(WINNER_P1); goto Play_again; // To play again } } // check based on eating other player if (blobs[PLAYER2].valid == 0) { // P1 wins game_over(WINNER_P1); game_over(WINNER_P1); goto Play_again; // To play again } else if (blobs[PLAYER1].valid == 0) { // P2 || AI wins game_over(WINNER_P2); game_over(WINNER_P1); goto Play_again; // To play again } // In both single- and multi-player modes, display the score(s) in an appropriate manner. // *** if (num_player == SINGLE_PLAYER) { // disp score top right of screen char scoreBanner[40]; sprintf(scoreBanner,"Score:%d ", score1); uLCD.background_color(BGRD_COL); uLCD.textbackground_color(RED);//BGRD_COL); uLCD.locate(10,0); uLCD.puts(scoreBanner); //GS_locate(sync, SCREEN_P1, 12,0); // GS_locate(GSYNC* gs, char screen, int x, int y) //GS_puts(sync, SCREEN_P1, bannerScore, strlen(bannerScore)); // void GS_puts(GSYNC* gs, char screen, char* str, int strlen) } else if (num_player == MULTI_PLAYER) { // disp score top right of screen char bannerScore[40]; sprintf(bannerScore,"MS: P1: %2d \n P2: %2d ", score1, score2); GS_locate(sync, SCREEN_BOTH, 9,0); // GS_locate(GSYNC* gs, char screen, int x, int y) GS_puts(sync, SCREEN_BOTH, bannerScore, sizeof(bannerScore)); // void GS_puts(GSYNC* gs, char screen, char* str, int strlen) } // Use the game synchronizer API to get the button values from both players' mbeds. p1_buttons = GS_get_p1_buttons(sync); p2_buttons = GS_get_p2_buttons(sync); // Use the game synchronizer API to get the accelerometer values from both players' mbeds. GS_get_p1_accel_data(sync, &ax1, &ay1, &az1); GS_get_p2_accel_data(sync, &ax2, &ay2, &az2); // If the magnitude of the p1 x and/or y accelerometer values exceed ACC_THRESHOLD, // set the blob 0 velocities to be proportional to the accelerometer values. // If in multi-player mode and the magnitude of the p2 x and/or y accelerometer values exceed ACC_THRESHOLD, // set the blob 0 velocities to be proportional to the accelerometer values. // ****/ float scalFact = 1000*(5/3)/(blobs[PLAYER1].rad * 0.5); if (abs(ax1) >= ACC_THRESHOLD) blobs[PLAYER1].vx = ax1 * scalFact; else blobs[PLAYER1].vx = 0; if (abs(ay1) >= ACC_THRESHOLD) blobs[PLAYER1].vy = ay1 * scalFact; else blobs[PLAYER1].vy = 0; // Undraw the world bounding rectangle (use BGRD_COL). // *** rect_bl_x = 0 - blobs[PLAYER1].old_x; rect_bl_y = 0 - blobs[PLAYER1].old_y; rect_ur_x = WORLD_WIDTH - blobs[PLAYER1].old_x; rect_ur_y = WORLD_HEIGHT - blobs[PLAYER1].old_y; GS_rectangle(sync, SCREEN_P1, rect_bl_x, rect_bl_y, rect_ur_x, rect_ur_y, BGRD_COL); // multi-player mode if (num_player == MULTI_PLAYER) { rect_bl_x = 0 - blobs[PLAYER2].old_x; rect_bl_y = 0 - blobs[PLAYER2].old_y; rect_ur_x = WORLD_WIDTH - blobs[PLAYER2].old_x; rect_ur_y = WORLD_HEIGHT - blobs[PLAYER2].old_y; GS_rectangle(sync, SCREEN_P2, rect_bl_x, rect_bl_y, rect_ur_x, rect_ur_y, BGRD_COL); } // Loop over all blobs // *** for (int i = 0; i < NUM_BLOBS; i++) { // *** if (blobs[i].delete_now == 1) { blob_x = blobs[i].posx - blobs[PLAYER1].old_x; blob_y = blobs[i].posy - blobs[PLAYER1].old_y; GS_circle(sync, SCREEN_P1, blob_x, blob_y, blobs[i].rad, BGRD_COL); if (num_player == MULTI_PLAYER) { blob_x = blobs[i].posx - blobs[PLAYER2].old_x; blob_y = blobs[i].posy - blobs[PLAYER2].old_y; GS_circle(sync, SCREEN_P2, blob_x, blob_y, blobs[i].rad, BGRD_COL); } blobs[i].delete_now = 0; } // Use the blob positions and velocities, as well as the time_step to compute the new position of the blob. // *** blobs[i].old_x = blobs[i].posx; blobs[i].old_y = blobs[i].posy; blobs[i].posx += blobs[i].vx * time_step; blobs[i].posy += blobs[i].vy * time_step; // If the current blob is blob 0, iterate over all blobs and check if they are close enough to eat or be eaten. // In multi-player mode, if the player 0 blob is eaten, player 1 wins and vise versa. // If blob 0 eats some food, increment score1. // *** if (i == PLAYER1) { for (int j = 1; j < NUM_BLOBS; j++) { if (j == PLAYER1) continue; // skip self if (blobs[j].valid == 0) continue; // skip invalid blobs // get dist between two blobs float dist2 = BLOB_dist2(blobs[i], blobs[j]); if (sqrt(dist2) < blobs[i].rad) { // danger zone, eat or be eaten if (blobs[i].rad > blobs[j].rad) { // P1 is bigger, so P1 eats blobs[j].valid = 0; // eaten blob is now invalid blobs[i].rad = blobs[i].rad + 4; // P1 inc. size and score score1++; // ... playSound(hitTune); // undraw smaller sized blob // void GS_circle(GSYNC* gs, char screen, int x , int y , int radius, int color) GS_circle(sync, SCREEN_P1, 0, 0, (blobs[i].rad-1), BGRD_COL); if (num_player == MULTI_PLAYER) { blob_x = blobs[i].posx - blobs[PLAYER2].old_x; blob_y = blobs[i].posy - blobs[PLAYER2].old_y; // void GS_circle(GSYNC* gs, char screen, int x , int y , int radius, int color) GS_circle(sync, SCREEN_P2, blob_x, blob_y, (blobs[i].rad-1), BGRD_COL); } if (j == PLAYER2 && num_player == MULTI_PLAYER) { pc.printf("NOT HERE\n"); game_over(WINNER_P1); // P2 loses game_over(WINNER_P1); goto Play_again; // To play again } } else if (blobs[i].rad < blobs[j].rad) { // P1 is smaller, so P1 is eaten blobs[i].valid = 0; // eaten blob is now invalid game_over(WINNER_P2); // P2 || AI wins game_over(WINNER_P1); goto Play_again; // To play again } } } } // If the current blob is blob 1 and we are playing in multi-player mode, iterate over all blobs and check // if they are close enough to eat or be eaten. In multi-player mode, if the player 1 blob is eaten, player 0 wins and vise versa. // If blob1 eats some food, increment score 2. // *** if (i == PLAYER2) { for (int j = 0; j < NUM_BLOBS; j++) { if (j == PLAYER2) continue; // skip self if (blobs[j].valid == 0) continue; // skip invalid blobs // get dist between two blobs float dist2 = BLOB_dist2(blobs[i], blobs[j]); if (sqrt(dist2) < blobs[i].rad) { if (blobs[i].rad > blobs[j].rad) { blobs[j].valid = 0; blobs[i].rad = blobs[i].rad + 4; score2++; playSound(hitTune); GS_circle(sync, SCREEN_P2, 0, 0, (blobs[i].rad-1), BGRD_COL); if (num_player == MULTI_PLAYER) { blob_x = blobs[i].posx - blobs[PLAYER1].old_x; blob_y = blobs[i].posy - blobs[PLAYER1].old_y; GS_circle(sync, SCREEN_P1, blob_x, blob_y, (blobs[i].rad-1), BGRD_COL); } if (j == PLAYER1 && num_player == MULTI_PLAYER) { game_over(WINNER_P2); game_over(WINNER_P1); goto Play_again; // To play again } } else if (blobs[i].rad < blobs[j].rad) { blobs[i].valid = 0; if (j == PLAYER1 && num_player == MULTI_PLAYER) { game_over(WINNER_P1); game_over(WINNER_P1); goto Play_again; // To play again } } } } } BLOB_constrain2world(&blobs[i]); } // Iterate over all blobs and draw them at their newly computed positions. Reference their positions to the player blobs. // That is, on screen 1, center the world on blob 0 and reference all blobs' position to that of blob 0. // On screen 2, center the world on blob 1 and reference all blobs' position tho that of blob 1. // *** for (int i = 0; i < NUM_BLOBS; i++) { if (blobs[i].valid == 1) { blob_x = blobs[i].posx - blobs[PLAYER1].posx; blob_y = blobs[i].posy - blobs[PLAYER1].posy; GS_circle(sync, SCREEN_P1, blob_x, blob_y, blobs[i].rad, blobs[i].color); if (num_player == MULTI_PLAYER) { blob_x = blobs[i].posx - blobs[PLAYER2].posx; blob_y = blobs[i].posy - blobs[PLAYER2].posy; GS_circle(sync, SCREEN_P2, blob_x, blob_y, blobs[i].rad, blobs[i].color); } } blobs[i].delete_now = 1; } // Redraw the world boundary rectangle. // *** rect_bl_x = 0 - blobs[PLAYER1].old_x; rect_bl_y = 0 - blobs[PLAYER1].old_y; rect_ur_x = WORLD_WIDTH - blobs[PLAYER1].old_x; rect_ur_y = WORLD_HEIGHT - blobs[PLAYER1].old_y; GS_rectangle(sync, SCREEN_P1, rect_bl_x, rect_bl_y, rect_ur_x, rect_ur_y, BORDER_COL); // multi-player mode if (num_player == MULTI_PLAYER) { rect_bl_x = 0 - blobs[PLAYER2].posx; rect_bl_y = 0 - blobs[PLAYER2].posy; rect_ur_x = WORLD_WIDTH - blobs[PLAYER2].posx; rect_ur_y = WORLD_HEIGHT - blobs[PLAYER2].posy; GS_rectangle(sync, SCREEN_P2, rect_bl_x, rect_bl_y, rect_ur_x, rect_ur_y, BORDER_COL); } // Update the screens by calling GS_update. GS_update(sync); 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]; } }