ECE 2035 final project

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

Revision:
2:22d36e7740f1
Parent:
0:35660d7952f7
--- a/main.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/main.cpp	Mon Apr 15 12:25:08 2019 +0000
@@ -5,11 +5,23 @@
 #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 ();
 
 /**
@@ -20,6 +32,12 @@
     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;
 
 /**
@@ -29,13 +47,124 @@
 #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)
 {
-    return NO_ACTION;
+    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;
+    }
 }
 
 /**
@@ -50,6 +179,7 @@
 #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
@@ -60,17 +190,356 @@
     // You can define functions like "go_up()" that get called for each case.
     switch(action)
     {
-        case GO_UP:     break;
-        case GO_LEFT:   break;            
-        case GO_DOWN:   break;
-        case GO_RIGHT:  break;
-        case ACTION_BUTTON: break;
-        case MENU_BUTTON: break;
-        default:        break;
+        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 
@@ -78,7 +547,24 @@
  * 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();
     
@@ -103,9 +589,21 @@
             
             // Figure out what to draw
             DrawFunc draw = NULL;
-            if (init && i == 0 && j == 0) // Only draw the player on init
+            if (init && i == 0 && j == 0 && get_here(Player.x, Player.y)->walkable != 2) // Only draw the player on init
             {
-                draw_player(u, v, Player.has_key);
+                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
@@ -135,8 +633,8 @@
     }
 
     // Draw status bars    
-    draw_upper_status();
-    draw_lower_status();
+    draw_upper_status(Player.x,Player.y);
+    draw_lower_status(Player.health, Player.num_phats);
 }
 
 
@@ -161,6 +659,59 @@
     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();
 }
 
@@ -175,17 +726,31 @@
     // 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)
     {
@@ -193,11 +758,15 @@
         Timer t; t.start();
         
         // Actuall do the game update:
-        // 1. Read inputs        
-        // 2. Determine action (get_action)        
+        // 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();