ECE 2035 final project
Dependencies: mbed wave_player 4DGL-uLCD-SE MMA8452
main.cpp
- Committer:
- npatel387
- Date:
- 2019-04-15
- Revision:
- 2:22d36e7740f1
- Parent:
- 0:35660d7952f7
File content as of revision 2:22d36e7740f1:
// Project includes #include "globals.h" #include "hardware.h" #include "map.h" #include "graphics.h" #include "speech.h" int omnipotent = 0; int mapToggle = 0; int finished = 0; int walk = 0; // Functions in this file int get_action (GameInputs inputs); int update_game (int action); void draw_game (int init); void init_main_map (); void init_second_map(); int go_up(int x, int y, int i); int go_down(int x, int y, int i); int go_right(int x, int y, int i); int go_left(int x, int y, int i); int interact(int x, int y); int NPC_move(int x, int y); int main (); /** * The main game state. Must include Player locations and previous locations for * drawing to work properly. Other items can be added as needed. */ struct { int x,y; // Current locations int px, py; // Previous locations int has_key; int omnipotent; int has_sword; int has_shield; int has_platebody; int health; int num_phats; } Player; /** * Given the game inputs, determine what kind of update needs to happen. * Possbile return values are defined below. */ #define NO_ACTION 0 #define ACTION_BUTTON 1 #define MENU_BUTTON 2 #define OMNIPOTENT 7 #define GO_LEFT 3 #define GO_LEFT2 10 #define GO_RIGHT 4 #define GO_RIGHT2 11 #define GO_UP 5 #define GO_UP2 12 #define GO_DOWN 6 #define GO_DOWN2 13 #define BAD_END 8 #define GOOD_END 9 char *questStartLine1 = "Wow a knight!what"; char *questStartLine2 = "perfect timing!"; char *questStartLine3 = "I beg you,please"; char *questStartLine4 = "defeat the evil"; char *questStartLine5 = "dragon Elvarg!"; char *questStartLine6 = "He resides in a"; char *questStartLine7 = "cave to the NEast"; char *questStartLine8 = "You'll need an"; char *questStartLine9 = "antifire shield"; char *questStartLine10 = "and Excalibur!"; char *questStartLine11 = "I hear Excalibur"; char *questStartLine12 = "can be found in"; char *questStartLine13 = "the same cave."; char *questStartLine14 = "It'll be embedded"; char *questStartLine15 = "in a stone there."; char *questStartLine16 = "Take my antifire"; char *questStartLine17 = "shield, man."; char *questStartLine18 = "If you do defeat"; char *questStartLine19 = "Elvarg, take"; char *questStartLine20 = "the key he drops."; char *questStartLine21 = "It unlocks his"; char *questStartLine22 = "treasure room"; char *questStartLine23 = "to the south."; char *questStartLine24 = "Good luck!"; char *questStartLine25 = "Come back when"; char *questStartLine26 = "you're done!"; char *questHasShield1 = "Go to the cave,"; char *questHasShield2 = "find Excalibur,"; char *questHasShield3 = "and defeat Elvarg"; char *questHasSword1 = "Go fight Evlarg!"; char *questHasPlatebody1 = "Thank you!!!!"; char *questHasPlatebody2 = "You have helped"; char *questHasPlatebody3 = "me out.I am"; char *questHasPlatebody4 = "very grateful!"; char *findSword1 = "You pull and"; char *findSword2 = "wield Excalibur."; char *elvarg1 = "You approach"; char *elvarg2 = "Elvarg attacks..."; char *elvarg3a1 = "With no shield,"; char *elvarg3a2 = "you are burnt to"; char *elvarg3a3 = "a crisp.(-10 HP)"; char *elvarg3b1 = "You have no sword"; char *elvarg3b2 = "Your punches have"; char *elvarg3b3 = "no effect so you"; char *elvarg3b4 = "are badly wounded"; char *elvarg3b5 = "(-9 HP)"; char *elvarg3c1 = "Using Excalibur &"; char *elvarg3c2 = "the shield you"; char *elvarg3c3 = "defeat Elvarg w/"; char *elvarg3c4 = "only minor wounds"; char *elvarg3c5 = "(-3 HP).He drops"; char *elvarg3c6 = "the key to his"; char *elvarg3c7 = "treasure room!"; int get_action(GameInputs inputs) { if(Player.health <= 0) { return BAD_END; } else if(finished) { return GOOD_END; } else if(!inputs.b1){ return ACTION_BUTTON; } else if(!inputs.b2){ return OMNIPOTENT; } else if(!inputs.b3){ return MENU_BUTTON; } else if(inputs.ax >= .2){ if(inputs.ax >= .4) return GO_LEFT2; else return GO_LEFT; } else if(inputs.ax <= -.3){ if(inputs.ax <= -.5) return GO_RIGHT2; else return GO_RIGHT; } else if(inputs.ay >= .3){ if(inputs.ay >= .5) return GO_DOWN2; else return GO_DOWN; } else if(inputs.ay <= -.2){ if(inputs.ay <= -.4) return GO_UP2; else return GO_UP; } else{ return NO_ACTION; } } /** * Update the game state based on the user action. For example, if the user * requests GO_UP, then this function should determine if that is possible by * consulting the map, and update the Player position accordingly. * * Return values are defined below. FULL_DRAW indicates that for this frame, * draw_game should not optimize drawing and should draw every tile, even if * the player has not moved. */ #define NO_RESULT 0 #define GAME_OVER 1 #define FULL_DRAW 2 #define RUN 3 int update_game(int action) { // Save player previous location before updating Player.px = Player.x; Player.py = Player.y; // Do different things based on the each action. // You can define functions like "go_up()" that get called for each case. switch(action) { case GO_UP: if(go_up(Player.x, Player.y, 0)) return FULL_DRAW; break; case GO_UP2: if(go_up(Player.x, Player.y,1)) return RUN; break; case GO_LEFT: if(go_left(Player.x, Player.y, 0)) return FULL_DRAW; break; case GO_LEFT2: if(go_left(Player.x, Player.y, 1)) return RUN; break; case GO_DOWN: if(go_down(Player.x, Player.y, 0)) return FULL_DRAW; break; case GO_DOWN2: if(go_down(Player.x, Player.y, 1)) return RUN; break; case GO_RIGHT: if(go_right(Player.x, Player.y, 0)) return FULL_DRAW; break; case GO_RIGHT2: if(go_right(Player.x, Player.y, 1)) return RUN; break; case ACTION_BUTTON: if(interact(Player.x, Player.y)) return FULL_DRAW; break; case OMNIPOTENT: //toggle omnipotent mode Player.omnipotent = !omnipotent; omnipotent = !omnipotent; break; case MENU_BUTTON: //open menu draw_menu(Player.omnipotent, Player.has_sword, Player.has_shield, Player.has_platebody, Player.has_key); return FULL_DRAW; case BAD_END: return BAD_END; case GOOD_END: return GOOD_END; default: return NPC_move(Player.x, Player.y); } return NO_RESULT; } //Functions to move player int go_up(int x, int y, int i) { MapItem *item = get_north(x, y); MapItem *item2 = get_north(x,y-1); if((item->walkable && item->type != PLANT2) || Player.omnipotent) { if((i && item2->walkable && item2->type != PLANT2) || Player.omnipotent) { Player.y = Player.y - 2; return RUN; } Player.y--; return 1; } else if(item->type == PLANT2) { Player.health--; speaker.period(1.0/150.0); // 500hz period speaker =0.25; //25% duty cycle - mid range volume wait(.02); speaker=0.0; // turn off audio wait(0.5); return 1; } else if(item->type == ROLLING && item2 == NULL) { map_erase(x,y-1); add_rolling(x,y-2); Player.y--; return 1; } return 0; } int go_down(int x, int y, int i) { MapItem *item = get_south(x, y); MapItem *item2 = get_south(x, y+1); if((item->walkable && item->type != PLANT2) || Player.omnipotent) { if((i && item2->walkable && item2->type != PLANT2) || Player.omnipotent) { Player.y = Player.y + 2; return RUN; } Player.y++; return 1; } else if(item->type == PLANT2) { Player.health--; speaker.period(1.0/150.0); // 500hz period speaker =0.25; //25% duty cycle - mid range volume wait(.02); speaker=0.0; // turn off audio wait(0.5); return 1; } else if(item->type == ROLLING && item2 == NULL) { map_erase(x,y+1); add_rolling(x,y+2); Player.y++; return 1; } return 0; } int go_left(int x, int y, int i) { MapItem *item = get_west(x, y); MapItem *item2 = get_west(x-1,y); if((item->walkable && item->type != PLANT2) || Player.omnipotent) { if((i && item2->walkable && item2->type != PLANT2) || Player.omnipotent) { Player.x = Player.x - 2; return RUN; } Player.x--; return 1; } else if(item->type == PLANT2) { Player.health--; speaker.period(1.0/150.0); // 500hz period speaker =0.25; //25% duty cycle - mid range volume wait(.02); speaker=0.0; // turn off audio wait(0.5); return 1; } else if(item->type == ROLLING && item2 == NULL) { map_erase(x-1,y); add_rolling(x-2,y); Player.x--; return 1; } return 0; } int go_right(int x, int y, int i) { MapItem *item = get_east(x, y); MapItem *item2 = get_east(x+1, y); if((item->walkable && item->type != PLANT2) || Player.omnipotent) { if((i && item2->walkable && item2->type != PLANT2) || Player.omnipotent) { Player.x = Player.x + 2; return RUN; } Player.x++; return 1; } else if(item->type == PLANT2) { Player.health--; speaker.period(1.0/150.0); // 500hz period speaker =0.25; //25% duty cycle - mid range volume wait(.02); speaker=0.0; // turn off audio wait(0.5); return 1; } else if(item->type == ROLLING && item2 == NULL) { map_erase(x+1,y); add_rolling(x+2,y); Player.x++; return 1; } return 0; } int interact(int x, int y) { MapItem *north = get_north(x,y); MapItem *south = get_south(x,y); MapItem *east = get_east(x,y); MapItem *west = get_west(x,y); if(north->type == STARTNPC || south->type == STARTNPC || east->type == STARTNPC || west->type == STARTNPC) { if(Player.has_platebody) { speech(questHasPlatebody1, questHasPlatebody2, questHasPlatebody3, questHasPlatebody4); finished = 1; return 1; } else if(!Player.has_platebody && Player.has_key) { speech("Search the", "treasure room", "first! Then", "come talk"); return 1; } else if(Player.has_sword) { speech(questHasSword1, "", "", ""); return 1; } else if(Player.has_shield ) { speech(questHasShield1, questHasShield2, questHasShield3, ""); return 1; } else { speech(questStartLine1, questStartLine2, questStartLine3, questStartLine4); speech(questStartLine5, questStartLine6, questStartLine7, questStartLine8); speech(questStartLine9, questStartLine10, questStartLine11, questStartLine12); speech(questStartLine13, questStartLine14, questStartLine15, questStartLine16); speech(questStartLine17, questStartLine18, questStartLine19, questStartLine20); speech(questStartLine21, questStartLine22, questStartLine23, questStartLine24); speech(questStartLine25, questStartLine26,"",""); Player.has_shield = 1; return 1; } } else if(north->type == CAVE || south->type == CAVE || east->type == CAVE || west->type == CAVE) { if(mapToggle == 0) { mapToggle = !mapToggle; set_active_map(1); Player.x = 5; Player.y = 5; } else { mapToggle = !mapToggle; set_active_map(0); Player.x = 39; Player.y = 4; } return 1; } else if(north->type == SWORDINSTONE || south->type == SWORDINSTONE || east->type == SWORDINSTONE || west->type == SWORDINSTONE) { if(Player.has_shield) { Player.has_sword = 1; speech(findSword1, findSword2, "", ""); map_erase(15,15); draw_plant(15,15); } else { speech("You should", "talk to the man", "where you started", "first"); } return 1; } else if(north->type == ELVARG || south->type == ELVARG || east->type == ELVARG || west->type == ELVARG) { speech(elvarg1, elvarg2, "", ""); if(!Player.has_shield) { speech(elvarg3a1, elvarg3a2, elvarg3a3, ""); Player.health = Player.health - 10; return 1; } else if(!Player.has_sword) { speech(elvarg3b1, elvarg3b2, elvarg3b3, elvarg3b4); speech(elvarg3b5, "", "", ""); Player.health = Player.health - 9; return 1; } else { Player.has_key = 1; speech(elvarg3c1, elvarg3c2, elvarg3c3, elvarg3c4); speech(elvarg3c5, elvarg3c6, elvarg3c7, ""); map_erase(10,10); Player.health = Player.health - 3; return 1; } } else if(north->type == GATE || south->type == GATE || east->type == GATE || west->type == GATE) { if(Player.has_key) { speech("You unlock the", "gate with the key", "", ""); map_erase(10,45); return 1; } else { speech("Requires Elvarg's", "key to open", "", ""); return 1; } } else if(north->type == TREASURE || south->type == TREASURE || east->type == TREASURE || west->type == TREASURE) { Player.has_platebody = 1; speech("You are amazed", "to find a", "legendary rune", "platebody."); speech("you equip the", "legendary armor.", "Time to return", "to that weird"); speech("guy. His request", "has been", "fulfilled.", ""); return 1; } else if(north->type == PHAT || south->type == PHAT || east->type == PHAT || west->type == PHAT) { if(Player.num_phats == 0) speech("find all 5", "hidden party", "hats!", ""); Player.num_phats++; if(Player.num_phats == 5) { speech("you found all", "5 party hats!", "You are very", "special!"); } if(north->type == PHAT) map_erase(x, y-1); if(south->type == PHAT) map_erase(x, y+1); if(east->type == PHAT) map_erase(x+1, y); if(west->type == PHAT) map_erase(x-1, y); return 1; } return 0; } int NPC_move(int x, int y) { if(!((Player.x == (7+!walk)) && (Player.y == 7)) && (map_width() == 50)) { wait_ms(200); map_erase(7+walk, 7); walk = !walk; add_startNPC(7+walk,7); wait_ms(200); return FULL_DRAW; } return 0; } /** * Entry point for frame drawing. This should be called once per iteration of * the game loop. This draws all tiles on the screen, followed by the status * bars. Unless init is nonzero, this function will optimize drawing by only * drawing tiles that have changed from the previous frame. */ void draw_game(int init) { if(init == BAD_END) { speaker.period(1.0/150.0); // 500hz period speaker =0.25; //25% duty cycle - mid range volume wait(.5); speaker=0.0; // turn off audio wait(0.5); draw_bad(); wait(10000); } if(init == GOOD_END) { draw_good(); wait(10000); } // Draw game border first if(init) draw_border(); // Iterate over all visible map tiles for (int i = -5; i <= 5; i++) // Iterate over columns of tiles { for (int j = -4; j <= 4; j++) // Iterate over one column of tiles { // Here, we have a given (i,j) // Compute the current map (x,y) of this tile int x = i + Player.x; int y = j + Player.y; // Compute the previous map (px, py) of this tile int px = i + Player.px; int py = j + Player.py; // Compute u,v coordinates for drawing int u = (i+5)*11 + 3; int v = (j+4)*11 + 15; // Figure out what to draw DrawFunc draw = NULL; if (init && i == 0 && j == 0 && get_here(Player.x, Player.y)->walkable != 2) // Only draw the player on init { if(init == RUN) { draw_player(u,v,4); wait_ms(100); } if(Player.has_platebody) draw_player(u, v, 3); else if(Player.has_sword) draw_player(u, v, 2); else if(Player.has_shield) draw_player(u ,v, 1); else draw_player(u ,v, 0); continue; } else if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) // Current (i,j) in the map { MapItem* curr_item = get_here(x, y); MapItem* prev_item = get_here(px, py); if (init || curr_item != prev_item) // Only draw if they're different { if (curr_item) // There's something here! Draw it { draw = curr_item->draw; } else // There used to be something, but now there isn't { draw = draw_nothing; } } } else if (init) // If doing a full draw, but we're out of bounds, draw the walls. { draw = draw_wall; } // Actually draw the tile if (draw) draw(u, v); } } // Draw status bars draw_upper_status(Player.x,Player.y); draw_lower_status(Player.health, Player.num_phats); } /** * Initialize the main world map. Add walls around the edges, interior chambers, * and plants in the background so you can see motion. */ void init_main_map() { // "Random" plants Map* map = set_active_map(0); for(int i = map_width() + 3; i < map_area(); i += 39) { add_plant(i % map_width(), i / map_width()); } pc.printf("plants\r\n"); pc.printf("Adding walls!\r\n"); add_wall(0, 0, HORIZONTAL, map_width()); add_wall(0, map_height()-1, HORIZONTAL, map_width()); add_wall(0, 0, VERTICAL, map_height()); add_wall(map_width()-1, 0, VERTICAL, map_height()); pc.printf("Walls done!\r\n"); //draw in treasure room add_wall(6, 45, VERTICAL, 4); add_wall(7, 45, HORIZONTAL, 3); add_gate(10,45); add_wall(11, 45, HORIZONTAL, 3); add_wall(14, 45, VERTICAL, 4); add_startNPC(7,7); pc.printf("NPCs!\r\n"); add_boulder(3,3); add_cave(40,4); pc.printf("Cave!\r\n"); add_rolling(39,4); add_rolling(41,4); add_rolling(40,5); add_rolling(40,3); add_treasure(10,47); pc.printf("Treasure!\r\n"); add_phat(45,45); add_phat(25,25); add_phat(10,48); print_map(); } void init_second_map() { // "Random" plants Map* map = set_active_map(1); for(int i = map_width() + 3; i < map_area(); i += 39) { add_plant2(i % map_width(), i / map_width()); } pc.printf("plants\r\n"); pc.printf("Adding walls!\r\n"); add_wall(0, 0, HORIZONTAL, map_width()); add_wall(0, map_height()-1, HORIZONTAL, map_width()); add_wall(0, 0, VERTICAL, map_height()); add_wall(map_width()-1, 0, VERTICAL, map_height()); pc.printf("Walls done!\r\n"); //add sprites add_cave(4,5); add_elvarg(10,10); add_swordInStone(15,15); add_phat(3,10); add_phat(10,17); print_map(); } /** * Program entry point! This is where it all begins. * This function orchestrates all the parts of the game. Most of your * implementation should be elsewhere - this holds the game loop, and should * read like a road map for the rest of the code. */ int main() { // First things first: initialize hardware ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!"); draw_start(); // Initialize the maps maps_init(); init_second_map(); init_main_map(); // Initialize game state set_active_map(0); Player.x = Player.y = 5; Player.has_key = 0; Player.has_sword = 0; Player.has_shield = 0; Player.has_platebody = 0; Player.health = 10; // Initial drawing uLCD.filled_rectangle(0, 0, 127, 8, BLACK); uLCD.filled_rectangle(0, 119, 127, 127, BLACK); draw_game(true); // Variables GameInputs in; int action; int draw; // Main game loop while(1) { // Timer to measure game update speed Timer t; t.start(); // Actuall do the game update: // 1. Read inputs in = read_inputs(); // 2. Determine action (get_action) action = get_action(in); // 3. Update game (update_game) draw = update_game(action); // 3b. Check for game over // 4. Draw frame (draw_game) draw_game(draw); // 5. Frame delay t.stop(); int dt = t.read_ms(); if (dt < 100) wait_ms(100 - dt); } }