ECE 2036 Project
Dependencies: mbed wave_player 4DGL-uLCD-SE
main.cpp
- Committer:
- abraha2d
- Date:
- 2019-11-21
- Revision:
- 2:2042f29de6b7
- Parent:
- 0:cf4396614a79
File content as of revision 2:2042f29de6b7:
/* Gatech ECE2035 2017 FALL MAZE RUNNER * Copyright (c) 2017 Gatech ECE2035 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Include header files for platform #include "mbed.h" // Include header files for pacman project #include "globals.h" #include "math_extra.h" #include "physics.h" #include "game.h" #include "wall.h" #include "doublely_linked_list.h" // Hardware initialization DigitalIn left_pb(p21); // push button DigitalIn right_pb(p22); // push button DigitalIn up_pb(p23); // push button DigitalIn down_pb(p24); // push button uLCD_4DGL uLCD(p9,p10,p11); // LCD (serial tx, serial rx, reset pin;) Serial pc(USBTX,USBRX); // used by Accelerometer MMA8452 acc(p28, p27, 100000); // Accelerometer //SDFileSystem sd(p5, p6, p7, p8, "sd"); // SD card and filesystem DigitalOut redLED(p25); // Red LED DigitalOut greenLED(p26); // Green LED Speaker speaker(p18); // Speaker // Menu screen drawing functions void do_main_menu(); void do_setup_menu(); void do_help_menu(); void do_level_start(int); void do_level_complete(int, int); void do_game_over(); // Level creation method declaration DLinkedList* create_blank_level(); DLinkedList* create_level_1(); DLinkedList* create_level_2(); DLinkedList* create_level_3(); // Parameters. Declared in globals.h const float mass = 0.001; const int radius = 4; const float bounce = 0.5; int sound = 1; /** Main() is where you start your implementation */ int main() { //////////////////////////// // Power-on initialization //////////////////////////// // Turn up the serial data rate so we don't lag uLCD.baudrate(3000000); pc.baud(115200); // Initialize the buttons // Each *_pb variable is 0 when pressed left_pb.mode(PullUp); right_pb.mode(PullUp); up_pb.mode(PullUp); down_pb.mode(PullUp); // Other hardware initialization here (SD card, speaker, etc.) DLinkedList* levels = create_dlinkedlist(); insertTail(levels, create_level_1()); insertTail(levels, create_level_2()); insertTail(levels, create_level_3()); do_main_menu(); /////////////// // Reset loop /////////////// // This is where control between major phases of the game happens // This is a good place to add choose levels, add the game menu, etc. // Start with the first level DLinkedList* arena = (DLinkedList*)getHead(levels); int level = 1; int gameOver = 0; while(gameOver == 0) { do_level_start(level); uLCD.cls(); // (Re)Initialze game state Physics state = {0}; int ix, iy; state.px = ix = ((Ball*)getTail(arena))->x; // Initial position of ball state.py = iy = ((Ball*)getTail(arena))->y; state.vx = 0.0; // Initial velocity of ball state.vy = 0.0; // Delegate to the game loop to execute the level // run_game() is in game.cpp int ret = run_game(arena, &state); // If we hit the goal, advance to the next level if (ret <= 30) { do_level_complete(level++, ret); // Destroy the arena and entities once we're done with the level destroyList(arena); // Get the next level arena = (DLinkedList*)getNext(levels); // If the next level is NULL, game over! if (arena == NULL) { gameOver = 1; } } else { if (ret == 32) { // Show help screen do_help_menu(); } else { // Collision effect redLED = 1; for (int i = 4; i < 29; i++) { redLED = !redLED; int tone = (29 - i) * 5 + 100; speaker.PlayNote(tone, 0.01, sound); uLCD.circle(64, 64, i, RED); uLCD.circle(64, 64, i - 1, 0xFFCC00); uLCD.circle(64, 64, i - 2, WHITE); uLCD.circle(64, 64, i - 3, 0); } } // If we hit a pothole, restart the level by redrawing all elements // and resetting the state ArenaElement* elem = (ArenaElement*)getHead(arena); do { switch(elem->type) { case WALL: // Redraw walls ((Wall*)elem)->should_draw = 1; break; case BALL: // Reset ball position ((Ball*)elem)->x = ix; ((Ball*)elem)->y = iy; break; case HOLE: // Redraw holes ((Hole*)elem)->should_draw = 1; break; case GOAL: // Redraw goal ((Goal*)elem)->should_draw = 1; break; default: break; } } while(elem = (ArenaElement*)getNext(arena)); } } do_game_over(); } void do_main_menu() { int cont = 1; while (cont) { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n"); uLCD.printf(" Maze Runner! "); uLCD.printf("\n\n"); uLCD.printf(" Play "); uLCD.printf("\n"); uLCD.printf(" Setup "); uLCD.printf("\n"); uLCD.printf(" Help "); uLCD.printf("\n\n"); uLCD.rectangle(15, 34, 112, 51, WHITE); uLCD.rectangle(15, 51, 112, 67, WHITE); uLCD.rectangle(15, 67, 112, 84, WHITE); uLCD.rectangle(16, 35, 111, 51, WHITE); uLCD.rectangle(16, 51, 111, 67, WHITE); uLCD.rectangle(16, 67, 111, 83, WHITE); int offset = 35; uLCD.rectangle(16, 0 + offset, 111, 16 + offset, BLUE); int rpb = right_pb; int upb = up_pb; int dpb = down_pb; int rpb2 = rpb; int upb2 = upb; int dpb2 = dpb; int cont2 = 1; while(cont2) { int crpb = right_pb; int cupb = up_pb; int cdpb = down_pb; if (!cupb && upb && upb2) { uLCD.rectangle(16, 0 + offset, 111, 16 + offset, WHITE); if (offset > 35) { offset -= 16; } uLCD.rectangle(16, 0 + offset, 111, 16 + offset, BLUE); speaker.PlayNote(100, 0.01, sound); } if (!cdpb && dpb && dpb2) { uLCD.rectangle(16, 0 + offset, 111, 16 + offset, WHITE); if (offset < 67) { offset += 16; } uLCD.rectangle(16, 0 + offset, 111, 16 + offset, BLUE); speaker.PlayNote(100, 0.01, sound); } if (!crpb && rpb && rpb2) { uLCD.rectangle(16, 0 + offset, 111, 16 + offset, GREEN); speaker.PlayNote(100, 0.01, sound); wait(0.25); if (offset == 51) { do_setup_menu(); cont2 = 0; } else if (offset == 67) { do_help_menu(); cont2 = 0; } else { cont = 0; cont2 = 0; } } rpb2 = rpb; upb2 = upb; dpb2 = dpb; rpb = crpb; upb = cupb; dpb = cdpb; } } } void do_setup_menu() { int cont = 1; while (cont) { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n"); uLCD.printf(" Setup "); uLCD.printf("\n\n"); if (sound) { uLCD.printf(" Sound ON "); } else { uLCD.printf(" Sound OFF "); } int offset = 35; uLCD.rectangle(16, 0 + offset, 111, 16 + offset, BLUE); int lpb = left_pb; int rpb = right_pb; int cont2 = 1; while(cont2) { int clpb = left_pb; int crpb = right_pb; if (!crpb && rpb) { uLCD.rectangle(16, 0 + offset, 111, 16 + offset, GREEN); wait(0.25); if (sound == 1) { sound = 0; } else { sound = 1; } speaker.PlayNote(100, 0.01, sound); cont2 = 0; } if (!clpb && lpb) { speaker.PlayNote(100, 0.01, sound); cont = 0; cont2 = 0; } lpb = clpb; rpb = crpb; } } } void do_help_menu() { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n"); uLCD.printf(" Help "); uLCD.printf("\n\n"); uLCD.printf("Tilt the game to "); uLCD.printf("get through the "); uLCD.printf("maze to the "); uLCD.color(GREEN); uLCD.printf("green "); uLCD.color(WHITE); uLCD.printf("dot. Don't touch "); uLCD.printf("the "); uLCD.color(RED); uLCD.printf("red"); uLCD.color(WHITE); uLCD.printf(" dots! "); uLCD.printf("\n"); uLCD.color(BLUE); uLCD.printf("UP"); uLCD.color(WHITE); uLCD.printf(" saves state. "); uLCD.printf("\n"); uLCD.color(BLUE); uLCD.printf("DOWN"); uLCD.color(WHITE); uLCD.printf(" jumps to the "); uLCD.printf("last saved state. "); while(left_pb) {} speaker.PlayNote(100, 0.01, sound); } void do_level_start(int level) { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n\n\n"); uLCD.printf(" Level %d ", level); uLCD.printf("\n\n\n"); uLCD.rectangle(16, 19, 103, 51, WHITE); uLCD.printf(" "); for (int i = 3; i > 0; i--) { redLED = 1; uLCD.printf("%i... ", i); speaker.PlayNote(293.665, 0.25, sound); redLED = 0; wait(0.75); } greenLED = 1; uLCD.printf("\n\n Go!"); speaker.PlayNote(391.995, 0.75, sound); greenLED = 0; } void do_level_complete(int level, int time) { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n\n\n"); uLCD.printf(" Level %d \n", level); uLCD.printf(" Complete! "); uLCD.printf("\n\n\n"); uLCD.printf(" Score: %d/30 ", time); uLCD.rectangle(16, 19, 103, 67, WHITE); greenLED = 1; speaker.PlayNote(391.995, 0.12, sound); greenLED = 0; wait(0.12); greenLED = 1; speaker.PlayNote(493.883, 0.12, sound); speaker.PlayNote(587.330, 0.24, sound); greenLED = 0; wait(1); } void do_game_over() { uLCD.cls(); uLCD.color(WHITE); uLCD.printf("\n\n\n\n"); uLCD.printf(" Game Over! "); uLCD.printf("\n\n\n"); uLCD.rectangle(16, 19, 103, 51, WHITE); uLCD.printf(" Press the blue "); uLCD.printf(" button to play "); uLCD.printf(" again! "); greenLED = 1; speaker.PlayNote(587.330, 0.2, sound); greenLED = 0; wait(0.2); greenLED = 1; speaker.PlayNote(587.330, 0.1, sound); wait(0.1); greenLED = 0; speaker.PlayNote(587.330, 0.2, sound); greenLED = 1; speaker.PlayNote(493.883, 0.2, sound); greenLED = 0; speaker.PlayNote(587.330, 0.1, sound); wait(0.1); greenLED = 1; speaker.PlayNote(783.991, 0.5, sound); greenLED = 0; } /** Creates the first level. */ DLinkedList* create_level_1() { DLinkedList* arena = create_dlinkedlist(); // Initialize the walls Wall* walls[12]; walls[0] = create_wall(HORIZONTAL, 0, 2, 127, bounce); // top walls[1] = create_wall(HORIZONTAL, 0, 127, 127, bounce);// bottom walls[2] = create_wall(VERTICAL, 0, 2, 127, bounce); // left walls[3] = create_wall(VERTICAL, 127, 2, 127, bounce); // right walls[4] = create_wall(VERTICAL, 21, 21, 84, bounce); walls[5] = create_wall(VERTICAL, 42, 2, 42, bounce); walls[6] = create_wall(VERTICAL, 63, 21, 106, bounce); walls[7] = create_wall(VERTICAL, 84, 64, 32, bounce); walls[8] = create_wall(VERTICAL, 42, 84, 21, bounce); walls[9] = create_wall(HORIZONTAL, 21, 64, 42, bounce); walls[10] = create_wall(HORIZONTAL, 21, 105, 21, bounce); walls[11] = create_wall(HORIZONTAL, 84, 64, 43, bounce); // Add the walls to the arena for (int i = 0; i < 12; i++) insertTail(arena, (void*)walls[i]); // Initialize the goal Goal* goal = (Goal*) malloc(sizeof(Goal)); goal->type = GOAL; goal->x = 95; goal->y = 80; goal->should_draw = 1; // Add goal to the arena insertTail(arena, (void*)goal); // Initialize the ball Ball* ball = (Ball*) malloc(sizeof(Ball)); ball->type = BALL; ball->x = 31; ball->y = 95; // Add ball to the arena insertTail(arena, (void*)ball); return arena; } /** Creates the second level. */ DLinkedList* create_level_2() { DLinkedList* arena = create_dlinkedlist(); // Initialize the walls Wall* walls[15]; walls[0] = create_wall(HORIZONTAL, 0, 2, 127, bounce); // top walls[1] = create_wall(HORIZONTAL, 0, 127, 127, bounce);// bottom walls[2] = create_wall(VERTICAL, 0, 2, 127, bounce); // left walls[3] = create_wall(VERTICAL, 127, 2, 127, bounce); // right walls[4] = create_wall(VERTICAL, 64, 2, 21, bounce); walls[5] = create_wall(HORIZONTAL, 0, 21, 32, bounce); walls[6] = create_wall(VERTICAL, 32, 21, 43, bounce); walls[7] = create_wall(VERTICAL, 96, 21, 22, bounce); walls[8] = create_wall(HORIZONTAL, 64, 43, 63, bounce); walls[9] = create_wall(HORIZONTAL, 32, 64, 32, bounce); walls[10] = create_wall(HORIZONTAL, 64, 85, 32, bounce); walls[11] = create_wall(VERTICAL, 64, 85, 42, bounce); walls[12] = create_wall(HORIZONTAL, 0, 85, 32, bounce); walls[13] = create_wall(VERTICAL, 32, 85, 22, bounce); walls[14] = create_wall(HORIZONTAL, 96, 107, 31, bounce); // Add the walls to the arena for (int i = 0; i < 15; i++) insertTail(arena, (void*)walls[i]); // Initialize a hole Hole* hole = (Hole*) malloc(sizeof(Hole)); hole->type = HOLE; hole->x = 96; hole->y = 64; hole->should_draw = 1; // Add hole to the arena insertTail(arena, (void*)hole); // Initialize the goal Goal* goal = (Goal*) malloc(sizeof(Goal)); goal->type = GOAL; goal->x = 112; goal->y = 21; goal->should_draw = 1; // Add goal to the arena insertTail(arena, (void*)goal); // Initialize the ball Ball* ball = (Ball*) malloc(sizeof(Ball)); ball->type = BALL; ball->x = 16; ball->y = 96; // Add ball to the arena insertTail(arena, (void*)ball); return arena; } /** Creates the third level. */ DLinkedList* create_level_3() { DLinkedList* arena = create_dlinkedlist(); // Initialize the walls Wall* walls[15]; walls[0] = create_wall(HORIZONTAL, 0, 2, 127, bounce); // top walls[1] = create_wall(HORIZONTAL, 0, 127, 127, bounce);// bottom walls[2] = create_wall(VERTICAL, 0, 2, 127, bounce); // left walls[3] = create_wall(VERTICAL, 127, 2, 127, bounce); // right walls[4] = create_wall(HORIZONTAL, 0, 18, 107, bounce); walls[5] = create_wall(VERTICAL, 107, 18, 92, bounce); walls[6] = create_wall(HORIZONTAL, 64, 110, 43, bounce); walls[7] = create_wall(HORIZONTAL, 43, 91, 42, bounce); walls[8] = create_wall(VERTICAL, 43, 91, 36, bounce); walls[9] = create_wall(HORIZONTAL, 0, 91, 21, bounce); walls[10] = create_wall(VERTICAL, 21, 73, 18, bounce); walls[11] = create_wall(HORIZONTAL, 21, 73, 64, bounce); walls[12] = create_wall(VERTICAL, 85, 37, 36, bounce); walls[13] = create_wall(HORIZONTAL, 21, 37, 64, bounce); walls[14] = create_wall(HORIZONTAL, 0, 55, 43, bounce); // Add the walls to the arena for (int i = 0; i < 15; i++) insertTail(arena, (void*)walls[i]); // Initialize a hole Hole* hole = (Hole*) malloc(sizeof(Hole)); hole->type = HOLE; hole->x = 96; hole->y = 82; hole->should_draw = 1; // Add hole to the arena insertTail(arena, (void*)hole); // Initialize a hole Hole* hole2 = (Hole*) malloc(sizeof(Hole)); hole2->type = HOLE; hole2->x = 64; hole2->y = 55; hole2->should_draw = 1; // Add hole to the arena insertTail(arena, (void*)hole2); // Initialize the goal Goal* goal = (Goal*) malloc(sizeof(Goal)); goal->type = GOAL; goal->x = 11; goal->y = 82; goal->should_draw = 1; // Add goal to the arena insertTail(arena, (void*)goal); // Initialize the ball Ball* ball = (Ball*) malloc(sizeof(Ball)); ball->type = BALL; ball->x = 21; ball->y = 110; // Add ball to the arena insertTail(arena, (void*)ball); return arena; } /** Creates a level with only bounding walls and a ball. */ DLinkedList* create_blank_level() { DLinkedList* arena = create_dlinkedlist(); // Initialize the walls Wall* walls[4]; walls[0] = create_wall(HORIZONTAL, 0, 2, 127, bounce); // top walls[1] = create_wall(HORIZONTAL, 0, 127, 127, bounce);// bottom walls[2] = create_wall(VERTICAL, 0, 0, 127, bounce); // left walls[3] = create_wall(VERTICAL, 127, 0, 127, bounce); // right // Add the walls to the arena for (int i = 0; i < 4; i++) insertTail(arena, (void*)walls[i]); // Initialize the ball Ball* ball = (Ball*) malloc(sizeof(Ball)); ball->type = BALL; ball->x = 20; ball->y = 20; // Add ball to the arena // NOTE: The ball should always be last in the arena list, so that the other // ArenaElements have a chance to compute the Physics updates before the // ball applies forward euler method. insertTail(arena, (void*)ball); return arena; }