Project Submission (late)

Dependencies:   mbed

main.cpp

Committer:
el17tc
Date:
2019-05-10
Revision:
3:83e79d31930c
Parent:
2:43bb635db736

File content as of revision 3:83e79d31930c:

/*
ELEC2645 Embedded Systems Project
School of Electronic & Electrical Engineering
University of Leeds
Name: Thomas Caine
Username: el175c
Student ID Number: 201127594
Date: 10/05/2019
*/


#include "mbed.h"
#include "Gamepad.h"
#include "N5110.h"
#include "Maze.h"
#include "Vector2Di.h"
#include "Player.h"
#include "Drawer.h"
#include "MainMenu.h"
#include "DefeatMenu.h"
#include "VictoryMenu.h"

/* Note:
If it were up to me almost everything in this file would be in a Game object and main would only have game.init(); game.run(); in it
Unfortunately I have been plagued by L6312W the empty execution region error (not the warning) all the way through this project
and this is as good as I could get it in terms of object orientation.
As far as I'm aware this error is a bug with the mbed compiler of this version but it can be worked around.
Dock marks as you see fit for not encapsulating the other headers into a single class.
(but the other classes are nice and object-oriented, right?)
*/


N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);
Gamepad gamepad;
/** Causes the currentMenu's button index to be decremented, moving the cursor to the higher button
*/
void buttonPressedUp() {
    if (currentMenu->buttonIndex > 0) {
        currentMenu->buttonIndex -= 1;   
        currentButton = currentMenu->buttons[currentMenu->buttonIndex];
    }
    printf("currentMenu->buttonIndex = %d\n", currentMenu->buttonIndex);
}

/** Causes the currentMenu's button index to be incremented, moving the cursor to the lower button
*/
void buttonPressedDown() {
    if (currentMenu->buttonIndex < (currentMenu->numOfButtons - 1)) {
        currentMenu->buttonIndex += 1;
        currentButton = currentMenu->buttons[currentMenu->buttonIndex];
    }
    printf("currentMenu->buttonIndex = %d\n", currentMenu->buttonIndex);
}

Ticker arrowFlicker;
Ticker ingameCounter;
bool arrowFlickFlag = 1;
int ingameTime;

/** Funciton for drawing the ingame Timer
 */
void drawTimer() {
    lcd.drawRect(1,1,20,8,FILL_WHITE);
    std::stringstream ss;
    ss << ingameTime;
    std::string timeStr = "Time:" + ss.str();
    lcd.printString(timeStr.c_str(), 1,0);
}
/** Timer increment/decrement function
 * @brief depending on the timerFlag (toggled on or off) it will count up or down
 */
void timerFunc() {
    if (timerFlag)
        ingameTime--;
    else
        ingameTime++;
}

/** Funciton making the button selection arrow flicker
 * @brief aesthetically pleasing (i think).
 */
void selectionArrowFunc() {
    arrowFlickFlag = !arrowFlickFlag;
};

/** The main function
 * Due to constantly getting Empty Execution region errors this is a lot more full than it should be
 * refer to note at the top of main.cpp for more comments on the issue.
 */
int main() {
    gamepad.init();
    lcd.init();
    lcd.setContrast(0.5);
    lcd.normalMode();
    lcd.setBrightness(0.5);
    
    arrowFlicker.attach(&selectionArrowFunc,0.9);
    currentMenu = new MainMenu(&lcd);
    
    // program loop - never exits
    while (true) {
        // menu loop
        gamepad.check_event(Gamepad::START_PRESSED); // consume trailing input from last loop
        while (true) {
          
          if (gamepad.check_event(Gamepad::A_PRESSED)) {
            buttonPressedDown();
          }
          if (gamepad.check_event(Gamepad::Y_PRESSED)) {
            buttonPressedUp();
          }
          if (gamepad.check_event(Gamepad::X_PRESSED)) {
            currentButton->runBack();
            gamepad.check_event(Gamepad::X_PRESSED); // consume second input if it appeared
          }
          if (gamepad.check_event(Gamepad::B_PRESSED)) {
            currentButton->run();
            gamepad.check_event(Gamepad::B_PRESSED); // consume second input if it appeared
          }
          if (gamepad.check_event(Gamepad::START_PRESSED)) {
            currentButton->run();
            gamepad.check_event(Gamepad::START_PRESSED); // consume second input if it appeared
          }
          if (gamepad.check_event(Gamepad::BACK_PRESSED)) {
            delete currentMenu;
            currentMenu = new MainMenu(&lcd);
          }
          
          lcd.clear();
          currentMenu->draw();
          
          if (arrowFlickFlag)
            lcd.drawSprite((currentButton->x)-2,(currentButton->y),7,4, (int *)selectArrow2);
          
          lcd.refresh();
          if (beginFlag) {
            beginFlag = false;
            printf("begin flag is true\n");
            break;
          }
          sleep();
        }
        delete currentMenu;

        Maze maze;
        Player player(&maze);
        maze.selectMaze(mazeSize);
        player.pos.x = maze.startX;
        player.pos.y = maze.startY;
        Drawer drawer(&player, &lcd);
    
        if (timerFlag)
          ingameTime = maze.timeToFinish;
        else
          ingameTime = 0;
        ingameCounter.attach(&timerFunc, 1);
        arrowFlicker.detach();
        bool winFlag = false;
    
        // Main game loop
        while (true) {
            if (gamepad.check_event(Gamepad::Y_PRESSED)) {
                if (player.checkLocation(player.pos, 0, 2)) {
                    winFlag = true;
                }
                player.walk();
                wait(0.2);
                if (gamepad.check_event(Gamepad::Y_PRESSED)) {
                    printf("walked but input fired twice\n");
                }
            }
            if (gamepad.check_event(Gamepad::X_PRESSED)) {
                player.turnLeft();
                wait(0.2);
                if (gamepad.check_event(Gamepad::X_PRESSED)) {
                    printf("turned left but input fired twice\n");
                }
            }
            if (gamepad.check_event(Gamepad::B_PRESSED)) {
                player.turnRight();
                wait(0.2);
                if (gamepad.check_event(Gamepad::B_PRESSED)) {
                    printf("turned right but input fired twice\n");
                }
            }
            if (gamepad.check_event(Gamepad::A_PRESSED)) {
                player.stepBack();
                wait(0.2);
                if (gamepad.check_event(Gamepad::A_PRESSED)) {
                    printf("stepped back but input fired twice\n");
                }
            }
            if (gamepad.check_event(Gamepad::R_PRESSED)) {
                player.turnRight();
                wait(0.2);
                if (gamepad.check_event(Gamepad::R_PRESSED)) {
                    printf("turned right but input fired twice\n");
                }
            }
            if (gamepad.check_event(Gamepad::L_PRESSED)) {
                player.turnLeft();
                wait(0.2);
                if (gamepad.check_event(Gamepad::L_PRESSED)) {
                    printf("turned left but input fired twice\n");
                }
            }
            
            if (winFlag) {
                printf("Player has escaped the maze\n");
                // player has won, end the game loop
                winFlag = false;
                currentMenu = new VictoryMenu(&lcd);
                if (timerFlag) {
                    currentMenu->score = maze.timeToFinish + (ingameTime * 2);
                } else {
                    currentMenu->score = maze.timeToFinish + ((maze.timeToFinish*10)/ingameTime);
                }
                break;
            }
            if (timerFlag && (ingameTime <= 0)) {
                printf("Player has ran out of time\n");
                // player has lost, end the game loop
                currentMenu = new DefeatMenu(&lcd);
                currentMenu->score = 0;
                break;
            }
            printf("========\n");
            
            lcd.clear();
            drawer.drawScreen();
            drawTimer();
            lcd.refresh();
            
            sleep();
        }
    
        arrowFlicker.attach(&selectionArrowFunc,0.9);
        gamepad.check_event(Gamepad::START_PRESSED);
        while (true) {
          if (gamepad.check_event(Gamepad::B_PRESSED)) {
            buttonPressedDown();
          }
          if (gamepad.check_event(Gamepad::X_PRESSED)) {
            buttonPressedUp();
          }
          if (gamepad.check_event(Gamepad::A_PRESSED)) {
            //buttonActivate(*currentButton);
          }
          if (gamepad.check_event(Gamepad::START_PRESSED)) {
            currentButton->run();
          } 
          lcd.clear();
          currentMenu->draw();
          if (arrowFlickFlag) {
                lcd.drawSprite((currentButton->x)-2,(currentButton->y),7,4, 
                (int *)selectArrow2);
          }
          if (restartFlag) {
            restartFlag = false;
            delete currentMenu;
            currentMenu = new StartMenu(&lcd);
            break;
          }
          if (menuFlag) {
            menuFlag = false;
            delete currentMenu;
            currentMenu = new MainMenu(&lcd);
            break;
          }
          lcd.refresh();
          sleep();
        }
    }
}