Game For ECE 2035

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

main.cpp

Committer:
nasiromar
Date:
2021-12-03
Revision:
14:7225da81314a
Parent:
13:798a4dd14c7e
Child:
15:05592aaa468c

File content as of revision 14:7225da81314a:

// Project includes
#include "globals.h"
#include "hardware.h"
#include "map.h"
#include "graphics.h"
#include "speech.h"
#include "spells.h"
#include "actions.h"
#include "SDFileSystem.h"

// Functions in this file
int get_action (GameInputs inputs);
int update_game (int action);
void draw_game (int init);
void init_main_map ();
int main ();

FILE *wave_file;





/**
 * 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 spell;
    int god;
    int won;
    int HP,MP;
    int talked;
    int gobs_slain,eye_slain;
    int money;
    // You can add other properties for the player here
} 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 GO_LEFT 3
#define GO_RIGHT 4
#define GO_UP 5
#define GO_DOWN 6
#define GOD_MODE 7

#define TILT .25
int get_action(GameInputs inputs)
{

    if(inputs.ay > TILT) {      //Go in north direction if it is not blocked
        return GO_UP;
    }
    if(inputs.ay < TILT *-1) {     //Go in south direction if it is not blocked
        return GO_DOWN;
    }
    if(inputs.ax > TILT) {      //Go in north direction if it is not blocked
        return GO_RIGHT;
    }
    if(inputs.ax < TILT *-1) {     //Go in north direction if it is not blocked
        return GO_LEFT;
    }
    if(!inputs.b1) {
        wait(.5);
        return ACTION_BUTTON;
    }
    if(!inputs.b2) {
        wait(.5);
        return MENU_BUTTON;
    }
    if (!inputs.b3) {
        wait(.5);
        return GOD_MODE;
    } 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.
 */
// Game Life and Magic Points


int purchase;
bool on_off = false;


#define NO_RESULT 0
#define GAME_OVER 1
#define FULL_DRAW 2
int update_game(int action)
{
     //walk_goblin(0);    
     
    
 // 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.

    // Need to check if Claue has changed as well if whats in front of me is able to be walked into
    switch(action) {
        case GO_UP: {
            MapItem* north = get_north(Player.x,Player.y);
            if (north->walkable && north == NULL || north->type == (PORTAL || PLANT) && Player.y != 0 || Player.god ) {
                Player.y--;

            }
            break;
        }
        case GO_RIGHT: {
            MapItem* east = get_east(Player.x,Player.y);
            if (east->walkable && east == NULL || east->type == (PORTAL || PLANT) && Player.x != 0 || Player.god ) {
                Player.x++;
            }
            break;
        }
        case GO_DOWN:  {
            MapItem* south = get_south(Player.x,Player.y);
            if (south->walkable && south == NULL || south->type ==(PORTAL || PLANT) && Player.y != 0 || Player.god ) {
                Player.y++;
            }
            break;
        }
        case GO_LEFT: {
            MapItem* west = get_west(Player.x,Player.y);
            if (west->walkable && west == NULL || west->type == (PORTAL || PLANT) && Player.x != 0 || Player.god  ) {
                Player.x--;
            }
            break;
        }
        case ACTION_BUTTON: {
            MapItem* west = get_west(Player.x,Player.y);
            MapItem* south = get_south(Player.x,Player.y);
            MapItem* north = get_north(Player.x,Player.y);
            MapItem* east = get_east(Player.x,Player.y);
            MapItem* curr =  get_here(Player.x,Player.y);

            if((east->type == NPC||west->type == NPC||north->type == NPC||south->type == NPC)&& Player.has_key == 1) {
                npc_speech2();
            }

            if(east->type == NPC||west->type == NPC||north->type == NPC||south->type == NPC && Player.has_key == 0 ) {
                npc_speech1();
                Player.talked = 1;
            }
            
            if(east->type == NPCT||west->type == NPCT||north->type == NPCT||south->type == NPCT && Player.has_key == 0 ) {
                npc2_speech();
                Player.talked = 1;
            }

            if(north->type == PORTAL||south->type == PORTAL||east->type == PORTAL||west->type == PORTAL) {
                 set_active_map(1);
                Player.x = Player.y = 7;
            }
            
           
            
            if(east->type == ENEMY1||west->type == ENEMY1||north->type == ENEMY1||south->type == ENEMY1) {
                Player.HP-=2;
                fire_dmg();
                gob_dmg();
                Player.HP-=10;
                Player.x--;
                Player.y--;
                Player.gobs_slain += 1;
                map_delete(10,10);
            }
            
            if(east->type == ENEMY2||west->type == ENEMY2||north->type == ENEMY2||south->type == ENEMY2) {
                Player.HP-=12;
                gob_dmg();
                Player.x--;
                Player.y--;
                map_delete(5,7);
            }
            
            if(east->type == ENEMY||west->type == ENEMY||north->type == ENEMY||south->type == ENEMY) {
                Player.HP-=10;
                eye_dmg();
                Player.eye_slain += 1;
                Player.x--;
                Player.y--;
                map_delete(15,15);
            }
            
            if(east->type == CHEST||west->type == CHEST||north->type == CHEST||south->type == CHEST  && Player.MP < 100) {
                potion();
                Player.MP += 5;
            }
            
            if(east->type == CHESTT||west->type == CHESTT||north->type == CHESTT||south->type == CHESTT) {
                money_chest();
                Player.money += 2;
                //wave_file = fopen("/sd/rupee-collect.wav","r");
                //waver.play(wave_file);
                //fclose(wave_file);
            }
            
            if(east->type == VILL||west->type == VILL||north->type == VILL||south->type == VILL) {
                merch_speech1();
                init_store();
                purchase = store();
                
                if (purchase == POT && Player.money >= 4){
                    poti();
                    Player.money -= 4;
                    Player.MP += 8;
                    }
                
                 if (purchase == ELX && Player.money >= 5){
                    elx();
                    Player.money -= 5;
                    Player.HP += 10;
                    }
                
                 if (purchase == FRT && Player.money >= 2){
                    frt();
                    Player.money -= 2;
                    Player.HP += 6;
                    }
                if (Player.money <= 1){
                    cantbuy();
                    }
                
                merch_speech2();
            }
            

            if(north->type == DRAGON||south->type == DRAGON||east->type == DRAGON||west->type == DRAGON) {
                if ( Player.spell == WATER){
                    
                slay_dragon();
                Player.has_key = 1;
                }
                
                //walk_goblin(0);
            }

            if(north->type == PORTAl||south->type == PORTAl||east->type == PORTAl||west->type == PORTAl) {
                set_active_map(0);
                Player.x=20;
                Player.y = 36;
            }

            if((north->type == DOOR||south->type == DOOR||east->type == DOOR||west->type == DOOR)&&Player.has_key == 1) {
                Player.won = door_open();
            }
            
            if((north->type == DOOR||south->type == DOOR||east->type == DOOR||west->type == DOOR)&&Player.has_key == 0) {
                door_locked();
            }

            if((north->type == PLANT||south->type == PLANT||east->type == PLANT||west->type == PLANT||curr->type == PLANT)&&
                    (north->data == FRUIT||south->data == FRUIT||east->data == FRUIT||west->data == FRUIT||curr->data == FRUIT)) {
                if(Player.HP < 100) {
                    fruit();
                    Player.HP += 5;
                    north->data = NULL;
                    south->data = NULL;
                    east->data = NULL;
                    west->data = NULL;
                    curr->data = NULL;
                } else
                    no_fruit();
                




            }
        }
        break;
        case MENU_BUTTON: {
            init_spells();
            
            Player.spell = spell();   
            Player.MP -= 10;
            uLCD.locate(15,15);
            uLCD.printf("S:%1i",Player.spell);
        }
        break;
        case GOD_MODE: {

            Player.god = !Player.god;
            if (Player.god) {
                god_modeOn();
            } else
                god_modeOff();

        }
        break;

        default:

            break;
    }
    
    
    return NO_RESULT;

    
}

/**
 * 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)
{
    // 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) { // Only draw the player on init
                draw_player(u, v, Player.has_key);
                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,Player.money);
    draw_lower_status(Player.HP,Player.MP);
}


/**
 * Initialize the main world map. Add walls around the edges, interior chambers,
 * and plants in the background so you can see motion. Note: using the similar
 * procedure you can init the secondary map(s).
 */
void init_main_map()
{
    // "Random" plants
    Map* map = set_active_map(0);
    for(int i = map_width() + 9; 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");



    for(int i = 7; i < 13; i++) {
        for (int j = 23; j <31; j++) {
            add_kindom(j,i);
        }
    }

    add_chest2(20,20);
    add_chest2(5,8);
    add_chest2(33,20);
    add_chest2(14,16);
    add_chest2(40,15);

    add_npc(9,9);
    
    add_npc2(30,30);
    
    add_npc2(10,10);
    
    add_npc2(20,9);
    
    add_merch(12,16);
    
    for(int i = 11; i <= 13; i++){
        add_store(i,15);
        }
        
    add_fire(27,13);
    add_fire(25,13);
    
    add_door(26,12);

    add_portal(20,35);

    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()
{

    Player.HP = 100;
    Player.MP = 100;

    // MapItem* north = get_north(Player.x,Player.y);


    // First things first: initialize hardware
    ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");

    // Initialize the maps
    maps_init();
    init_main_map();
    init_dung();
    
    

    // Initialize game state
    set_active_map(0);
    Player.x = Player.y = 5;
    Player.money = 0;
    Player.spell = NULL;
    

    draw_start();

    //wave_file = fopen("/sd/godfather.wav","r");
    //waver.play(wave_file);
    //fclose(wave_file);

    while(1) {

        Timer t;
        t.start();
        GameInputs inp =  read_inputs();
        int action = get_action(inp);


        if( action == ACTION_BUTTON) {

            break;
        }
        t.stop();
        int dt = t.read_ms();
        if (dt < 100) wait_ms(100-dt);

    }


    // Initial drawing
    draw_game(true);
    // Main game loop
    while(1) {
        // Timer to measure game update speed
        Timer t;
        t.start();

        // Actually do the game update:
        // 1. Read inputs
        GameInputs input = read_inputs();
        // 2. Determine action (get_action)
        int action = get_action(input);
        // 3. Update game (update_game)
        update_game(action);
        // 3b. Check for game over
        if(Player.won == 1 || Player.HP <= 0) {
            draw_gameover();
            break;
        }
        // 4. Draw frame (draw_game)
        draw_game(true);

        // 5. Frame delay
        t.stop();
        int dt = t.read_ms();
        if (dt < 100) wait_ms(100 - dt);
    }
    //


}