Game

Dependencies:   mbed

main.cpp

Committer:
HenryWTriff
Date:
2020-05-22
Revision:
27:7e230a7891f8
Parent:
26:f1d3b7e31091

File content as of revision 27:7e230a7891f8:

/*
ELEC2645 Embedded Systems Project
School of Electronic & Electrical Engineering
University of Leeds
2019/20

Name: Henry Triff
Username: el18ht
Student ID Number: 201224295
Date: 10/02/2020

DIAGNOSTICS AND TEST FUNCTIONS
> I created a separate program that allows me to test functions of this code and to test and view the maps that i have
created. The code is 'quick and dirty' but works well. the controls are a little confusing. Stick moves the view of the track
around and X and A zoom in and out. Pots are used to show/hide different aspects of the map.
> It can be found here: https://os.mbed.com//users/HenryWTriff/code/ELEC2645_Project_el18ht_Map_Viewer/
*/

//DEBUG DEFINITIONS
//#define DEBUG

//LIBRARIES
#include "mbed.h"
#include "Gamepad.h"
#include "N5110.h"
#include "FXOS8700CQ.h"
#include "SDFileSystem.h"
#include "Graphics.h"
#include "Mechanics.h"
#include "Menu.h"
#include "LEDs.h"
#include "Ghost.h"
#include <string>

#ifndef STRUCTS
#define STRUCTS

//STRUCTS
struct Point_2D {
    float x;
    float y;
};

struct Line_2D {
    Point_2D from;
    Point_2D to;
};

struct Square_2D {
    Point_2D TL;
    Point_2D BR;
};
struct Triangle_2D {
    Point_2D TL;
    Point_2D BR;
    int Type; //The direction of the hypoentuse on the right angled triangle ( 1 = Top right, 2 = Bottom right, 3 = Bottom left, 4 = Top Left )
};

struct Sprite_2D {
    float x;
    float y;
    int type;
};

struct Map_Data {
    //Information about the number of elements in each array
    int number_of_track_lines;
    int number_of_dotted_lines;
    int number_of_sprites;
    int number_of_walls;
    int number_of_off_track_squares;
    int number_of_off_track_triangles;
    int number_of_out_of_bounds_squares;
    int number_of_out_of_bounds_triangles;
    int number_of_gates;
    int number_of_boost_plates;
};

struct Time {
    int mins;
    int secs;
    int milis;
};

struct Gyro_Data {
    float ax;
    float ay;
    float az;
    float mx;
    float my;
    float mz;
};

#endif

//GLOBAL VARIABLES
#ifndef ENUMS
#define ENUMS
enum track {Small, Medium, Large}; //Track Names
enum cars {Basic, Offroad, Drifter, Sportscar, Racecar, Stupid}; //Car Names (Stupid is now the alien space ship)
enum sprites {Flag, Helicopter, People_Standing_1, People_Standing_2, People_Cheering};
#endif

//OBJECTS
Gamepad Device;                                     //Controller
N5110 LCD;                                          //LCD
FXOS8700CQ Gyro(I2C_SDA,I2C_SCL);                   //Gyroscope
SDFileSystem SD(PTE3, PTE1, PTE2, PTE4, "sd");      //SD card (For recording ghost data)
Graphics Graphics;                                  //Graphics Class
Mechanics Mechanics;                                //Mechanics Class
Menu Menu;                                          //Menu Class
LEDs LEDs;                                          //LEDs Class
Ghost Ghost;                                        //Ghost Class (For racing against a previos version of you)

#include "Maps.h"

//Transform
int angle = 0; //The angle of roation of the track
Point_2D translation = {0,0}; //The translation of the track
float horizon_factor = 0.02; //The translation of the track
float squish = 0.15; //The amount of squish of the track

//Vehicle parameters
float speed; //Current speed (Rate of change of translation [see above] )
float max_speed; //Max speed the car can go
int handling; //The maximum rate of change of angle of the track per frame
float off_track_speed; //Maximum off track speed
float acceleration;
float deceleration;
int car_model = Basic;

//Mechanics
int lap_gate = 0; //The initial lap gate
int laps = 1; //The current lap number
int number_of_laps = 3;  //The number of laps
int race_time = 0; //The number of frames elapsed so far since the start of the race
bool ghost_enable = false;

//Game Settings
int game_fps = 60; //Frame rate
bool leds = true; //Turning the LEDs on / off (Useful for people with epilepsy as they flash quickly)
bool gyro_enabled = false; //Gyro steering option

int main()
{
#ifdef DEBUG
    printf("INITIALISATION\n");
#endif

    LCD.init(); //Initialising the LCD
    Device.init(); //Initialising the Gamepad
    Gyro.init(); //Initialising the gyro
    Graphics.Change_Contrast(LCD,Device); //Adust Contrast to the amount on the pot

#ifdef DEBUG
    printf("LOGO\n");
#endif

    //START LOGO
    Graphics.Draw_Logo(LCD);

    //MENU
#ifdef DEBUG
    printf("MENU\n");
#endif
    do {
        while(Menu.Main_Menu(LCD, Device) == true) {
            Ghost.SD_init(SD,LCD); //Format SD Card
        }
    } while(Menu.Game_Setup(LCD, Device) == false);

    //RETRIEVING STATIC VARIABLES FROM MENU CLASS
    car_model = Menu.Get_Car();
    number_of_laps = Menu.Get_Laps();
    ghost_enable = Menu.Get_Mode();
    leds = Menu.Get_Setting_LED();
    gyro_enabled = Menu.Get_Setting_Gyro();

    //CAR PARAMETERS SETUP
    max_speed = Mechanics.Get_Max_Speed(car_model);
    acceleration = Mechanics.Get_Acceleration(car_model);
    deceleration = Mechanics.Get_Deceleration(car_model);
    off_track_speed = Mechanics.Get_Off_Road_Speed(car_model);
    handling = Mechanics.Get_Handling(car_model);

#ifdef DEBUG
    printf("GAME RUN\n");
    printf("MAP: %i  LAPS: %i  CAR: %i\n",Menu.Get_Map(),number_of_laps, car_model);
#endif

    if(Menu.Get_Map() == Small) {

        while(1) { //Main Game While loop
            if(ghost_enable == true) { //If ghost mode is enabled
#ifdef DEBUG
                printf("READING GHOST DATA\n");
#endif
                Ghost.SD_Read(Small, car_model, SD); //Copy the ghost data from the SD card over to the flash memory (Make take a second)
            }

#ifdef DEBUG
            printf("COUNTDOWN\n");
#endif
            //COUNTDOWN
            for(int count = 3; count >= 0; count--) { //Loop for the countdown
                //Draw the map and the count down numbers
                LCD.clear();
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_1_Track_Lines,
                    (Line_2D *)Map_1_Track_Dotted_Lines,
                    (Line_2D *)Map_1_Walls,
                    (Sprite_2D *)Map_1_Sprites,
                    (Triangle_2D *)Map_1_Boost_Plates,
                    Map_1,
                    car_model,
                    Ghost.Play(false, race_time),
                    LCD
                );
                Graphics.Start_Sequence(count, LCD);
                LCD.refresh();
                LEDs.Start_Sequence(leds, count, Device); //Display the LED traffic light count down
                wait(1);
            }
            LEDs.Clear(Device);

#ifdef DEBUG
            printf("RACE START\n");
#endif

            while(laps <= number_of_laps) { //Loop until the number of laps have been completed
                //MECHANICS
                laps = Mechanics.Get_Laps(laps, Map_1_Gates, Map_1.number_of_gates, translation, lap_gate); //Get the current lap count
                lap_gate = Mechanics.Get_Gate(Map_1_Gates, Map_1.number_of_gates, translation, lap_gate); //Get the current lap_gate
                angle = Mechanics.Get_Angle(angle, handling, gyro_enabled, Gyro, Device); //Get the current angle
                translation = Mechanics.Get_Translation(translation, angle, speed, Map_1_Out_Of_Bounds_Square, Map_1_Out_Of_Bounds_Triangle, Map_1, Device); //Get the translation
                speed = Mechanics.Get_Speed(
                            speed,
                            max_speed,
                            acceleration,
                            deceleration,
                            off_track_speed,
                            translation,
                            Map_1_Off_Track_Square,
                            Map_1_Off_Track_Triangle,
                            Map_1_Out_Of_Bounds_Square,
                            Map_1_Out_Of_Bounds_Triangle,
                            Map_1_Boost_Plates,
                            Map_1,
                            Device
                        ); //Get the speed of the player

                //LEDS
                LEDs.Speed(leds, speed, max_speed, Device); //Change the LEDs depending on the speed

                //GHOST
                if(ghost_enable == true) { //If ghost mode is enabled
                    Ghost.Record(translation, race_time); //Record the position of the player
                }

                //GRAPHICS
                LCD.clear(); //Clear the screen buffer
                Graphics.Change_Contrast(LCD,Device); //Adjust the contrast
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_1_Track_Lines,
                    (Line_2D *)Map_1_Track_Dotted_Lines,
                    (Line_2D *)Map_1_Walls,
                    (Sprite_2D *)Map_1_Sprites,
                    (Triangle_2D *)Map_1_Boost_Plates,
                    Map_1,
                    car_model,
                    Ghost.Play(ghost_enable, race_time),
                    LCD
                ); //Draw the graphics
                Graphics.Draw_Laps(laps, LCD); //Draw the lap counter
                Graphics.Draw_Time(false, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the time
                LCD.refresh(); //Refresh the display
                wait((1 / float(game_fps))); //Wait for a short period of time
                race_time++; //Increase the race time

            }
            //RACE OVER
            LEDs.Clear(Device); //Turn off the LEDs
            LCD.clear();
            Graphics.Draw_Map(
                translation,
                angle,
                squish,
                horizon_factor,
                (Line_2D *) Map_1_Track_Lines,
                (Line_2D *)Map_1_Track_Dotted_Lines,
                (Line_2D *)Map_1_Walls,
                (Sprite_2D *)Map_1_Sprites,
                (Triangle_2D *)Map_1_Boost_Plates,
                Map_1,
                car_model,
                Ghost.Play(false, race_time),
                LCD
            ); //Draw the graphics
            Graphics.Finish(LCD); //Display the finish logo
            Graphics.Draw_Time(true, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the race time
            LCD.refresh(); //Refresh the display
            if(ghost_enable == true) { //If ghost mode enabled
#ifdef DEBUG
                printf("GHOST COPY\n");
#endif
                Ghost.Copy(race_time, Small, car_model, SD); //Copy over the ghost data to the SD card (if race time is quicker)
            }

            //RESET ALL VARIABLES
            angle = 0;
            Point_2D test = {0,0};
            translation = test;
            squish = 0.15;
            speed = 0;
            max_speed = 4;
            handling = 2;
            lap_gate = 0;
            laps = 1;
            race_time = 0;

            wait(3);

#ifdef DEBUG
            printf("LOOP\n");
#endif

        }
    } else if(Menu.Get_Map() == Medium) {
        while(1) {

            if(ghost_enable == true) { //If ghost mode is enabled
#ifdef DEBUG
                printf("READING GHOST DATA\n");
#endif
                Ghost.SD_Read(Medium, car_model, SD);//Copy the ghost data from the SD card over to the flash memory (Make take a second)
            }

#ifdef DEBUG
            printf("COUNTDOWN\n");
#endif

            //COUNTDOWN
            for(int count = 3; count >= 0; count--) {
                //Draw the map and the count down numbers
                LCD.clear();
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_2_Track_Lines,
                    (Line_2D *)Map_2_Track_Dotted_Lines,
                    (Line_2D *)Map_2_Walls,
                    (Sprite_2D *)Map_2_Sprites,
                    (Triangle_2D *)Map_2_Boost_Plates,
                    Map_2,
                    car_model,
                    Ghost.Play(false, race_time),
                    LCD
                );
                Graphics.Start_Sequence(count, LCD);
                LEDs.Start_Sequence(leds, count, Device); //Display the LED traffic light count down
                LCD.refresh();
                wait(1);
            }
            LEDs.Clear(Device);

#ifdef DEBUG
            printf("RACE START\n");
#endif

            while(laps <= number_of_laps) {
                //MECHANICS
                laps = Mechanics.Get_Laps(laps, Map_2_Gates, Map_2.number_of_gates, translation, lap_gate); //Get the current lap count
                lap_gate = Mechanics.Get_Gate(Map_2_Gates, Map_2.number_of_gates, translation, lap_gate); //Get the current lap_gate
                angle = Mechanics.Get_Angle(angle, handling, gyro_enabled, Gyro, Device); //Get the current angle
                translation = Mechanics.Get_Translation(translation, angle, speed, Map_2_Out_Of_Bounds_Square, Map_2_Out_Of_Bounds_Triangle, Map_2, Device); //Get the translation
                speed = Mechanics.Get_Speed(
                            speed,
                            max_speed,
                            acceleration,
                            deceleration,
                            off_track_speed,
                            translation,
                            Map_2_Off_Track_Square,
                            Map_2_Off_Track_Triangle,
                            Map_2_Out_Of_Bounds_Square,
                            Map_2_Out_Of_Bounds_Triangle,
                            Map_2_Boost_Plates,
                            Map_2,
                            Device
                        ); //Get the speed of the player
                //LEDS
                LEDs.Speed(leds, speed, max_speed, Device); //Change the LEDs depending on the speed

                //GHOST
                if(ghost_enable == true) { //If ghost mode is enabled
                    Ghost.Record(translation, race_time);  //Record the position of the player
                }

                //GRAPHICS
                LCD.clear(); //Clear the screen buffer
                Graphics.Change_Contrast(LCD,Device); //Adjust the contrast
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_2_Track_Lines,
                    (Line_2D *)Map_2_Track_Dotted_Lines,
                    (Line_2D *)Map_2_Walls,
                    (Sprite_2D *)Map_2_Sprites,
                    (Triangle_2D *)Map_2_Boost_Plates,
                    Map_2,
                    car_model,
                    Ghost.Play(ghost_enable, race_time),
                    LCD
                ); //Draw the graphics
                Graphics.Draw_Laps(laps, LCD); //Draw the lap counter
                Graphics.Draw_Time(false, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the time
                LCD.refresh(); //Refresh the display
                wait((1 / float(game_fps))); //Wait for a short period of time
                race_time++; //Increase the race time

            }


            LEDs.Clear(Device); //Turn off the LEDs
            LCD.clear();
            Graphics.Draw_Map(
                translation,
                angle,
                squish,
                horizon_factor,
                (Line_2D *) Map_2_Track_Lines,
                (Line_2D *)Map_2_Track_Dotted_Lines,
                (Line_2D *)Map_2_Walls,
                (Sprite_2D *)Map_2_Sprites,
                (Triangle_2D *)Map_2_Boost_Plates,
                Map_2,
                car_model,
                Ghost.Play(false, race_time),
                LCD
            ); //Draw the graphics
            Graphics.Finish(LCD); //Display the finish logo
            Graphics.Draw_Time(true, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the race time
            LCD.refresh(); //Refresh the display
            if(ghost_enable == true) { //If ghost mode enabled
#ifdef DEBUG
                printf("RACE START\n");
#endif
                Ghost.Copy(race_time, Medium, car_model, SD); //Copy over the ghost data to the SD card (if race time is quicker)
            }

            //RESET ALL VARIABLES
            angle = 0;
            Point_2D test = {0,0};
            translation = test;
            squish = 0.15;
            speed = 0;
            max_speed = 4;
            handling = 2;
            lap_gate = 0;
            laps = 1;
            race_time = 0;

            wait(3);

#ifdef DEBUG
            printf("LOOP\n");
#endif

        }
    } else if(Menu.Get_Map() == Large) {
        while(1) {

            if(ghost_enable == true) { //If ghost mode is enabled
#ifdef DEBUG
                printf("READING GHOST DATA\n");
#endif
                Ghost.SD_Read(Large, car_model, SD); //Copy the ghost data from the SD card over to the flash memory (Make take a second)
            }

#ifdef DEBUG
            printf("COUNTDOWN\n");
#endif

            //COUNTDOWN
            for(int count = 3; count >= 0; count--) { //Loop for the countdown
                //Draw the map and the count down numbers
                LCD.clear();
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_3_Track_Lines,
                    (Line_2D *)Map_3_Track_Dotted_Lines,
                    (Line_2D *)Map_3_Walls,
                    (Sprite_2D *)Map_2_Sprites,
                    (Triangle_2D *)Map_3_Boost_Plates,
                    Map_3,
                    car_model,
                    Ghost.Play(false, race_time),
                    LCD
                );
                Graphics.Start_Sequence(count, LCD);
                LCD.refresh();
                LEDs.Start_Sequence(leds, count, Device); //Display the LED traffic light count down
                wait(1);
            }
            LEDs.Clear(Device);

#ifdef DEBUG
            printf("RACE START\n");
#endif

            while(laps <= number_of_laps) { //Loop until the number of laps have been completed
                //MECHANICS
                laps = Mechanics.Get_Laps(laps, Map_3_Gates, Map_3.number_of_gates, translation, lap_gate); //Get the current lap count
                lap_gate = Mechanics.Get_Gate(Map_3_Gates, Map_3.number_of_gates, translation, lap_gate); //Get the current lap_gate
                angle = Mechanics.Get_Angle(angle, handling, gyro_enabled, Gyro, Device); //Get the current angle
                translation = Mechanics.Get_Translation(translation, angle, speed, Map_3_Out_Of_Bounds_Square, Map_3_Out_Of_Bounds_Triangle, Map_3, Device);//Get the translation
                speed = Mechanics.Get_Speed(
                            speed,
                            max_speed,
                            acceleration,
                            deceleration,
                            off_track_speed,
                            translation,
                            Map_3_Off_Track_Square,
                            Map_3_Off_Track_Triangle,
                            Map_3_Out_Of_Bounds_Square,
                            Map_3_Out_Of_Bounds_Triangle,
                            Map_3_Boost_Plates,
                            Map_3,
                            Device
                        );//Get the speed of the player

                //LEDS
                LEDs.Speed(leds, speed, max_speed, Device); //Change the LEDs depending on the speed

                //GHOST
                if(ghost_enable == true) { //If ghost mode is enabled
                    Ghost.Record(translation, race_time); //Record the position of the player
                }

                //GRAPHICS
                LCD.clear(); //Clear the screen
                Graphics.Change_Contrast(LCD,Device); //Adjust the contrast
                Graphics.Draw_Map(
                    translation,
                    angle,
                    squish,
                    horizon_factor,
                    (Line_2D *) Map_3_Track_Lines,
                    (Line_2D *)Map_3_Track_Dotted_Lines,
                    (Line_2D *)Map_3_Walls,
                    (Sprite_2D *)Map_3_Sprites,
                    (Triangle_2D *)Map_3_Boost_Plates,
                    Map_3,
                    car_model,
                    Ghost.Play(ghost_enable, race_time),
                    LCD
                ); //Draw the graphics
                Graphics.Draw_Laps(laps, LCD); //Draw the lap counter
                Graphics.Draw_Time(false, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the time
                LCD.refresh(); //Refresh the display
                wait((1 / float(game_fps))); //Wait for a short period of time
                race_time++; //Increase the race time
            }

            LEDs.Clear(Device); //Turn off the LEDs
            LCD.clear();
            Graphics.Draw_Map(
                translation,
                angle,
                squish,
                horizon_factor,
                (Line_2D *) Map_3_Track_Lines,
                (Line_2D *)Map_3_Track_Dotted_Lines,
                (Line_2D *)Map_3_Walls,
                (Sprite_2D *)Map_3_Sprites,
                (Triangle_2D *)Map_3_Boost_Plates,
                Map_3,
                car_model,
                Ghost.Play(false, race_time),
                LCD
            ); //Draw the graphics
            Graphics.Finish(LCD); //Display the finish logo
            Graphics.Draw_Time(true, Mechanics.Convert_To_Time(game_fps, race_time), LCD); //Draw the race time
            LCD.refresh(); //Refresh the display
            if(ghost_enable == true) { //If ghost mode enabled
#ifdef DEBUG
                printf("RACE START\n");
#endif
                Ghost.Copy(race_time, Large, car_model, SD); //Copy over the ghost data to the SD card (if race time is quicker)
            }

            //RESET ALL VARIABLES
            angle = 0;
            Point_2D test = {0,0};
            translation = test;
            squish = 0.15;
            speed = 0;
            max_speed = 4;
            handling = 2;
            lap_gate = 0;
            laps = 1;
            race_time = 0;
            wait(3);

#ifdef DEBUG
            printf("LOOP\n");
#endif

        }
    }
}