Game

Dependencies:   mbed

Graphics/Graphics.cpp

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

File content as of revision 27:7e230a7891f8:

#include "Graphics.h"

Graphics::Graphics()
{
}

Graphics::~Graphics()
{
}

//-----------
//  SPRITES
//-----------

#include "Sprites.h"

//--------------------------
//  MAIN GRAPHICS FUNCTION
//--------------------------
// This is the main function for the graphics.
// It is a LARGE function but it reduces the clutter in main.cpp
// This is run once every frame.

void Graphics::Draw_Map(Point_2D translation, int angle, float squish, float horizon_factor, Line_2D *Track_Lines, Line_2D *Track_Dotted_Lines, Line_2D *Track_Walls, Sprite_2D *Track_Sprites, Triangle_2D *Track_Boost_Plates, Map_Data map_info, int car_type, Point_2D ghost_position, N5110 &LCD)
{
    //Variable declaration
    enum cars {Basic, Offroad, Drifter, Sportscar, Racecar, Stupid};
    Line_2D Track_Lines_Transformed[map_info.number_of_track_lines];
    Line_2D Track_Dotted_Lines_Transformed[map_info.number_of_dotted_lines];
    Point_2D Transformed_Sprites[map_info.number_of_sprites];
    Line_2D Transformed_Walls[map_info.number_of_walls];
    Point_2D Transformed_Ghost;

    //Transforms the points of the track lines
    for(int i = 0; i < map_info.number_of_track_lines; i++) { //Iterates through the given track array
        Track_Lines_Transformed[i] = Track_Lines[i];
        //Translation
        Track_Lines_Transformed[i].from = Translate_Point(Track_Lines_Transformed[i].from, Round(translation.x), Round(translation.y));
        Track_Lines_Transformed[i].to = Translate_Point(Track_Lines_Transformed[i].to, Round(translation.x), Round(translation.y));
        //Rotation
        Track_Lines_Transformed[i].from = Rotate_Point(Track_Lines_Transformed[i].from, angle);
        Track_Lines_Transformed[i].to = Rotate_Point(Track_Lines_Transformed[i].to, angle);
        //Horizon
        Track_Lines_Transformed[i].from = Horizon_Point(Track_Lines_Transformed[i].from, horizon_factor);
        Track_Lines_Transformed[i].to = Horizon_Point(Track_Lines_Transformed[i].to, horizon_factor);
        //Squish
        Track_Lines_Transformed[i].from = Squish_Point(Track_Lines_Transformed[i].from, squish);
        Track_Lines_Transformed[i].to = Squish_Point(Track_Lines_Transformed[i].to, squish);
    }

    //Transforms the points of the dotted lines on the track
    for(int i = 0; i < map_info.number_of_dotted_lines; i++) { //Iterates through the given dotted lines array
        Track_Dotted_Lines_Transformed[i] = Track_Dotted_Lines[i];
        //Translation
        Track_Dotted_Lines_Transformed[i].from = Translate_Point(Track_Dotted_Lines_Transformed[i].from, Round(translation.x), Round(translation.y));
        Track_Dotted_Lines_Transformed[i].to = Translate_Point(Track_Dotted_Lines_Transformed[i].to, Round(translation.x), Round(translation.y));
        //Rotation
        Track_Dotted_Lines_Transformed[i].from = Rotate_Point(Track_Dotted_Lines_Transformed[i].from, angle);
        Track_Dotted_Lines_Transformed[i].to = Rotate_Point(Track_Dotted_Lines_Transformed[i].to, angle);
        //Horizon
        Track_Dotted_Lines_Transformed[i].from = Horizon_Point(Track_Dotted_Lines_Transformed[i].from, horizon_factor);
        Track_Dotted_Lines_Transformed[i].to = Horizon_Point(Track_Dotted_Lines_Transformed[i].to, horizon_factor);
        //Squish
        Track_Dotted_Lines_Transformed[i].from = Squish_Point(Track_Dotted_Lines_Transformed[i].from, squish);
        Track_Dotted_Lines_Transformed[i].to = Squish_Point(Track_Dotted_Lines_Transformed[i].to, squish);
    }

    //Transforms the points of the start flags
    for(int i = 0; i < map_info.number_of_sprites; i++) { //Iterates through the given flags array
        Transformed_Sprites[i].x = Track_Sprites[i].x;
        Transformed_Sprites[i].y = Track_Sprites[i].y;
        //Translation
        Transformed_Sprites[i] = Translate_Point(Transformed_Sprites[i], Round(translation.x), Round(translation.y));
        //Rotation
        Transformed_Sprites[i] = Rotate_Point(Transformed_Sprites[i], angle);
        //Horizon
        Transformed_Sprites[i] = Horizon_Point(Transformed_Sprites[i], horizon_factor);
        //Squish
        Transformed_Sprites[i] = Squish_Point(Transformed_Sprites[i], squish);
    }

    //Transforms the points of the  walls
    for(int i = 0; i < map_info.number_of_walls; i++) { //Iterates throught the given walls array
        Transformed_Walls[i] = Track_Walls[i];
        //Translation
        Transformed_Walls[i].from = Translate_Point(Transformed_Walls[i].from, Round(translation.x), Round(translation.y));
        Transformed_Walls[i].to = Translate_Point(Transformed_Walls[i].to, Round(translation.x), Round(translation.y));
        //Rotation
        Transformed_Walls[i].from = Rotate_Point(Transformed_Walls[i].from, angle);
        Transformed_Walls[i].to = Rotate_Point(Transformed_Walls[i].to, angle);
        //Horizon
        Transformed_Walls[i].from = Horizon_Point(Transformed_Walls[i].from, horizon_factor);
        Transformed_Walls[i].to = Horizon_Point(Transformed_Walls[i].to, horizon_factor);
        //Squish
        Transformed_Walls[i].from = Squish_Point(Transformed_Walls[i].from, squish);
        Transformed_Walls[i].to = Squish_Point(Transformed_Walls[i].to, squish);
    }

    //Transforms the points of the ghost position
    Transformed_Ghost = ghost_position;
    //Translation
    Transformed_Ghost = Translate_Point(Transformed_Ghost, Round(translation.x), Round(translation.y));
    //Rotation
    Transformed_Ghost = Rotate_Point(Transformed_Ghost, angle);
    //Horizon
    Transformed_Ghost = Horizon_Point(Transformed_Ghost, horizon_factor);
    //Squish
    Transformed_Ghost = Squish_Point(Transformed_Ghost, squish);
    Transformed_Ghost.x = Transformed_Ghost.x + 4;

    //Draws the track lines
    for(int i = 0; i < map_info.number_of_track_lines; i++) { //Iterates through each line
        Graphics_Draw_Line(Track_Lines_Transformed[i].from, Track_Lines_Transformed[i].to, true, LCD);
    }

    //Draws the dotted lines
    for(int i = 0; i < map_info.number_of_dotted_lines; i++) { //Iterates through each line
        Graphics_Draw_Line(Track_Dotted_Lines_Transformed[i].from, Track_Dotted_Lines_Transformed[i].to,false, LCD);
    }

    //Draws the boost plates
    for(int i = 0; i < map_info.number_of_boost_plates; i++) { //Iterates through each plate
        Graphics_Draw_Boost_Plate(Track_Boost_Plates[i], translation, angle, squish, LCD);
    }

    //Draws the ghost
    Graphics_Draw_Sprite(Transformed_Ghost, 8, 8, (int *)ghost, LCD);

    //Draws the walls
    for(int i = 0; i < map_info.number_of_walls; i++) {
        Graphics_Draw_Wall(Transformed_Walls[i].from, Transformed_Walls[i].to,4, LCD);
    }
    
    //Draws the flags
    for(int i = 0; i < map_info.number_of_sprites; i++) { //Iterates through each flag
        if(Track_Sprites[i].type == Flag) {
            Graphics_Draw_Sprite(Transformed_Sprites[i], 8, 8, (int *)flag, LCD);
        } else if(Track_Sprites[i].type == Helicopter) {
            Graphics_Draw_Sprite(Transformed_Sprites[i], 48, 24, (int *)helicopter, LCD);
        } else if(Track_Sprites[i].type == People_Cheering) {
            Graphics_Draw_Sprite(Transformed_Sprites[i], 8, 12, (int *)person_cheering, LCD);
        } else if(Track_Sprites[i].type == People_Standing_1) {
            Graphics_Draw_Sprite(Transformed_Sprites[i], 6, 12, (int *)person_standing_1, LCD);
        } else if(Track_Sprites[i].type == People_Standing_2) {
            Graphics_Draw_Sprite(Transformed_Sprites[i], 6, 12, (int *)person_standing_2, LCD);
        }
    }

    //Draws the players car
    Point_2D car_position = {0,0};
    if(car_type == Stupid) {
        Graphics_Draw_Sprite(car_position,8,8,(int *)stupid_car, LCD);
    } else if(car_type == Racecar) {
        Graphics_Draw_Sprite(car_position,8,8,(int *)race_car, LCD);
    } else if(car_type == Sportscar) {
        Graphics_Draw_Sprite(car_position,8,8,(int *)sports_car, LCD);
    } else if(car_type == Drifter) {
        Graphics_Draw_Sprite(car_position,8,8,(int *)drifter_car, LCD);
    } else if(car_type == Offroad) {
        Graphics_Draw_Sprite(car_position,8,8,(int *)offroad_car, LCD);
    } else {
        Graphics_Draw_Sprite(car_position,8,8,(int *)basic_car, LCD);
    }
}

//--------------
//  START LOGO
//--------------

void Graphics::Draw_Logo(N5110 &LCD) //Draw the game logo
{
    LCD.clear();
    LCD.drawSprite(0,0,48,84,(int *)logo);
    LCD.refresh();
    wait(1);
}

//-------------------
//  SCREEN SETTINGS
//-------------------

void Graphics::Change_Contrast(N5110 &LCD, Gamepad &Device) //Sets the contrast with a greater level of precision
{
    LCD.setContrast((0.35 + 0.2 * Device.read_pot1()));
}

//---------------------------
//  RACE START / END SCREEN
//---------------------------

//START
void Graphics::Start_Sequence(int state, N5110 &LCD) //Display the countdown numbers before the race starts
{
    Point_2D count_down_position = {0,8};
    if(state == 3) {
        Graphics_Draw_Sprite(count_down_position, 17, 17, (int *) count_down_3, LCD);
    } else if(state == 2) {
        Graphics_Draw_Sprite(count_down_position, 17, 17, (int *) count_down_2, LCD);
    } else if(state == 1) {
        Graphics_Draw_Sprite(count_down_position, 17, 17, (int *) count_down_1, LCD);
    } else if(state == 0) {
        Graphics_Draw_Sprite(count_down_position, 18, 18, (int *) count_down_0, LCD);
    }

}

//FINISH
void Graphics::Finish(N5110 &LCD) //When the race is over draw the cup symbol
{
    Point_2D finish_position = {0,8};
    Graphics_Draw_Sprite(finish_position, 16, 16, (int *) cup, LCD);
}

//--------------------
//  DRAW LAP COUNTER
//--------------------

void Graphics::Draw_Laps(int laps, N5110 &LCD) //Prints the lab counter in the bottom left corner
{
    if(laps == 1) {
        LCD.printString("1",0,5);
    } else if (laps == 2) {
        LCD.printString("2",0,5);
    } else if (laps == 3) {
        LCD.printString("3",0,5);
    } else if (laps == 4) {
        LCD.printString("4",0,5);
    } else if (laps == 5) {
        LCD.printString("5",0,5);
    }
}

//-------------------
//  DRAW RACE CLOCK
//-------------------

void Graphics::Draw_Time(bool finished, Time time, N5110 &LCD) //Displays the lap time
{
    if(finished == false) { //If the race is over, Print the time in the middle of the screen
        char min[1];
        sprintf(min, "%i", time.mins); //Converts min integer to char
        LCD.printString(min,47,5); //Prints the min char on the screen

        LCD.printString(":",52,5);

        if(time.secs < 10) { //If the number of seconds is less than 10
            LCD.printString("0",57,5); //Draw a 0
            char sec[1];
            sprintf(sec, "%i", time.secs); //Converts sec integer to char
            LCD.printString(sec,63,5); //Prints the sec char on the screen
        } else {
            char sec[2];
            sprintf(sec, "%i", time.secs); //Converts sec integer to char
            LCD.printString(sec,57,5); //Prints the sec char on the screen
        }

        LCD.printString(".",68,5);

        char mili[2];
        sprintf(mili, "%i", time.milis); //Convers mili integer to char
        LCD.printString(mili,73,5); //Prints the mili char on the screen
    } else { //If the race is still ongoing
        char min[1];
        sprintf(min, "%i", time.mins); //Convers min integer to char
        LCD.printString(min,23,0); //Prints the min char on the screen

        LCD.printString(":",28,0);

        if(time.secs < 10) { //If the number of seconds is less than 10
            LCD.printString("0",33,0); //Draw a 0
            char sec[1];
            sprintf(sec, "%i", time.secs); //Convers sec integer to char
            LCD.printString(sec,39,0); //Prints the sec char on the screen
        } else {
            char sec[2];
            sprintf(sec, "%i", time.secs); //Convers sec integer to char
            LCD.printString(sec,33,0); //Prints the sec char on the screen
        }

        LCD.printString(".",44,0);

        char mili[2];
        sprintf(mili, "%i", time.milis); //Convers mili integer to char
        LCD.printString(mili,49,0); //Prints the mili char on the screen
    }
}

//-------------------
//  TRANSFORMATIONS
//-------------------

//ROTATE
Point_2D Graphics::Rotate_Point(Point_2D point, float angle) //Rotates all points around the origin
{
    angle = (angle * PI)/180; //The angle given in degrees is changed into radian form
    float x_rotated = point.x * cos(angle) - point.y * sin(angle); //X-points are rotated about the origin
    float y_rotated = point.y * cos(angle) + point.x * sin(angle); //Y-points are rotated about the origin
    return {x_rotated, y_rotated};
}
//TRANSLATE
Point_2D Graphics::Translate_Point(Point_2D point, int translate_x, int translate_y) //Translates all point by a given translationg
{
    float x_translated = point.x - translate_x; //Translates the x-points
    float y_translated = point.y - translate_y; //Translates the y-points
    return {x_translated, y_translated};
}

//HORIZONED
Point_2D Graphics::Horizon_Point(Point_2D point, float horizon_factor) //Makes all points look like they are following the horizon
{
    float x_horizoned;
    if(point.x > 0) {
        x_horizoned = point.x - point.y * horizon_factor;
    } else {
        x_horizoned = point.x + point.y * horizon_factor;
    }
    return {x_horizoned, point.y};
}

//SQUISH
//To get the 3D perspective, the y-coordinate is reduced by a factor
Point_2D Graphics::Squish_Point(Point_2D point, float squish) //Squishes all y-coordinates by a factor
{
    float x_squish = point.x; //The x-coordinate remains the same
    float y_squish = point.y * squish; //The y-coordinate is reduced
    return {x_squish, y_squish};
}

//--------
//  MATH
//--------

//ROUNDING FLOATING POINT NUMBERS
int Graphics::Round(float number) //Simple function that rounds floating point numbers
{
    int number_int = (number * 10); //The number is multiplied by 10
    int remainder = number_int % 10; //The remainder when dividing by 10 is calculated
    if(remainder < 5) { //If the number is less than 5
        return ((number_int - remainder) / 10); //Round down
    } else {
        return ((number_int + (10 - remainder)) / 10); //Round up
    }
}

//CALCULATING THE GRADIENT OF A LINE
float Graphics::Gradient(Point_2D from, Point_2D to) //Calculates the gradient of the line between two points
{
    float change_in_y = to.y - from.y; //Calculates the change in the y-values of the two points
    float change_in_x = to.x - from.x; //Calculates the change in the x-values of the two points
    float gradient = change_in_y / change_in_x; //Calculates the gradient by doing dy/dx
    if(gradient < 0.001 && gradient > -0.001) { //If the gradient is aproximately 0
        return 0; //Return zero
    } else {
        return gradient; //Else return the gradient
    }
}

//CHECKING IF A GRADIENT IS VERY LARGE
bool Graphics::Gradient_Check_Infinate(Point_2D from, Point_2D to) //Checks to see if the gradient is vertical
{
    float change_in_x = to.x - from.x; //Calculates the change in the x-value
    if(change_in_x < 0.001 && change_in_x > -0.001) { //If the change in x value is very small
        return true;
    } else {
        return false;
    }
}

//-------------
//  DRAW LINE
//-------------

void Graphics::Graphics_Draw_Line(Point_2D from, Point_2D to, bool solid, N5110 &LCD) //Draw a line between two points on only the portion of the screen
{

    if( Gradient_Check_Infinate(from, to)  == false ) { //Checking to see if the line is vertical
        //Initialising variables
        Point_2D plot_x_from = {0,0};
        Point_2D plot_x_to = {0,0};
        Point_2D plot_y_from = {0,0};
        Point_2D plot_y_to = {0,0};

        float gradient = Gradient(from, to); // Calculating the gradient
        float y_intercept = (from.y - gradient * from.x); // Calulating the y intercept y - mx = c
        float x_intercept = (from.x - from.y / gradient); // Calculating the x intercept x - y/m = d

        if(gradient <= 1 && gradient >= -1) {
            //Reordering 'from' and 'to' so that the for loops below can use ++
            if(to.x < from.x) {
                plot_x_from = to;
                plot_x_to = from;
            } else {
                plot_x_from = from;
                plot_x_to = to;
            }
            if(solid == true) { //If the line is solid or dotted
                for(int x = Round(plot_x_from.x); x <= Round(plot_x_to.x); x++) { //Iterating through the x points
                    int y = -(Round((gradient * x) + y_intercept)); //Calculating the value of y for each x point
                    Point_2D plot_x = {x+42, y+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                    if(plot_x.x <= 84 && plot_x.x >= 0 && plot_x.y <=48 && plot_x.y >= 0) { //Checking to see if the point is on the screen
                        LCD.setPixel(plot_x.x, plot_x.y, true); //Plotting the points
                    }
                }
            } else {
                for(int x = Round(plot_x_from.x); x <= Round(plot_x_to.x); x+=2) { //Iterating through the x points
                    int y = -(Round((gradient * x) + y_intercept)); //Calculating the value of y for each x point
                    Point_2D plot_x = {x+42, y+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                    if(plot_x.x <= 84 && plot_x.x >= 0 && plot_x.y <=48 && plot_x.y >= 0) { //Checking to see if the point is on the screen
                        LCD.setPixel(plot_x.x, plot_x.y, true); //Plotting the points
                    }
                }
            }
        } else {
            //Reordering 'from' and 'to' so that the for loops below can use ++
            if(to.y < from.y) {
                plot_y_from = to;
                plot_y_to = from;
            } else {
                plot_y_from = from;
                plot_y_to = to;
            }
            if(solid == true) { //If the line is solid or dotted
                for(int y = Round(plot_y_from.y); y <= Round(plot_y_to.y); y++) { //Iterating through the Y points
                    int x = Round((y / gradient) + x_intercept); //Calculating the value of x for every y point
                    Point_2D plot_y = {x+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                    if(plot_y.x <= 84 && plot_y.x >= 0 && plot_y.y <=48 && plot_y.y >= 0) { //Checking to see if the point is on the screen
                        LCD.setPixel(plot_y.x, plot_y.y, true); //Plotting the points
                    }
                }
            } else {
                for(int y = Round(plot_y_from.y); y <= Round(plot_y_to.y); y+=2) { //Iterating through the Y points
                    int x = Round((y / gradient) + x_intercept); //Calculating the value of x for every y point
                    Point_2D plot_y = {x+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                    if(plot_y.x <= 84 && plot_y.x >= 0 && plot_y.y <=48 && plot_y.y >= 0) { //Checking to see if the point is on the screen
                        LCD.setPixel(plot_y.x, plot_y.y, true); //Plotting the points
                    }
                }
            }
        }

    } else {
        Point_2D plot_y_from = {0,0};
        Point_2D plot_y_to = {0,0};
        //Reordering from and to so that the for loops below can use ++
        if(to.y < from.y) {
            plot_y_from = to;
            plot_y_to = from;
        } else {
            plot_y_from = from;
            plot_y_to = to;
        }
        float x_intercept = from.x; //Calculating the x_intercept
        if(solid == true) { //If the line is solid or dotted
            for(int y = plot_y_from.y; y <= plot_y_to.y; y++) {
                Point_2D plot_y = {x_intercept+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                LCD.setPixel(plot_y.x, plot_y.y, true); //Plotting the points
            }
        } else {
            for(int y = plot_y_from.y; y <= plot_y_to.y; y+=2) {
                Point_2D plot_y = {x_intercept+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                LCD.setPixel(plot_y.x, plot_y.y, true); //Plotting the points
            }
        }
    }
}

//---------------
//  DRAW SPRITE
//---------------

void Graphics::Graphics_Draw_Sprite(Point_2D point, int x_size, int y_size, int *sprite, N5110 &LCD) //Similar to N5110 drawSprite function but mine uses the origin as poin 0,0 and allows for transparent pixels
{
    Point_2D zeroed_point = {Round(point.x) + 42 - (x_size / 2), Round(-point.y) + 36 - y_size};
    for (int i = 0; i < y_size; i++) {
        for (int j = 0 ; j < x_size ; j++) {
            int pixel = *((sprite+i*x_size)+j);
            if(pixel == 1 || pixel == 0) {
                int x = zeroed_point.x+j;
                int y = zeroed_point.y+i;
                if(x <= 84 && x >= 0 && y <= 48 && y >= 0) { //If the point is on the screen
                    LCD.setPixel(x,y, pixel);
                }
            }
        }
    }
}

//-------------
//  DRAW WALL
//-------------

void Graphics::Graphics_Draw_Wall(Point_2D from, Point_2D to, int height, N5110 &LCD) //Draw a line between two points on only the portion of the screen
{
    if(Gradient_Check_Infinate(from, to) == 0) { //Checking to see if the line is vertical
        //Declaring points
        Point_2D plot_x_from = {0,0};
        Point_2D plot_x_to = {0,0};
        Point_2D plot_y_from = {0,0};
        Point_2D plot_y_to = {0,0};

        float gradient = Gradient(from, to); // Calculating the gradient
        float y_intercept = (from.y - gradient * from.x); // Calulating the y intercept y - mx = c
        float x_intercept = (from.x - from.y / gradient); // Calculating the x intercept x - y/m = d

        if(gradient <= 1 && gradient >= -1) {
            //Reordering 'from' and 'to' so that the for loops below can use ++
            if(to.x < from.x) {
                plot_x_from = to;
                plot_x_to = from;
            } else {
                plot_x_from = from;
                plot_x_to = to;
            }
            for(int x = Round(plot_x_from.x); x <= Round(plot_x_to.x); x++) { //Iterating through the x points
                int y = -(Round((gradient * x) + y_intercept)); //Calculating the value of y for each x point
                Point_2D plot_x = {x+42, y+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                if(plot_x.x <= 84 && plot_x.x >= 0 && plot_x.y <=48 && plot_x.y >= 0) { //Checking to see if the point is on the screen
                    for(int y_add = 0; y_add < height; y_add++) { //To differentiate it from a line, 'heigh' number of pixels above the line are also drawn.  This gives the impression of height
                        LCD.setPixel(plot_x.x, plot_x.y - y_add, true); //Plotting the point
                    }
                }
            }
        } else {
            //Reordering 'from' and 'to' so that the for loops can use ++
            if(to.y < from.y) {
                plot_y_from = to;
                plot_y_to = from;
            } else {
                plot_y_from = from;
                plot_y_to = to;
            }
            for(int y = Round(plot_y_from.y); y <= Round(plot_y_to.y); y++) { //Iterating through the Y points
                int x = Round((y / gradient) + x_intercept); //Calculating the value of x for every y point
                Point_2D plot_y = {x+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
                if(plot_y.x <= 84 && plot_y.x >= 0 && plot_y.y <=48 && plot_y.y >= 0) { //Checking to see if the point is on the screen
                    for(int y_add = 0; y_add < height; y_add++) { //To differentiate it from a line, 'heigh' number of pixels above the line are also drawn. This gives the impression of height
                        LCD.setPixel(plot_y.x, plot_y.y - y_add, true); //Plotting the point
                    }
                }
            }
        }

    } else {
        //Declaring and initialising points
        Point_2D plot_y_from = {0,0};
        Point_2D plot_y_to = {0,0};
        //Reordering from and to so that the for loops below can use ++
        if(to.y < from.y) {
            plot_y_from = to;
            plot_y_to = from;
        } else {
            plot_y_from = from;
            plot_y_to = to;
        }
        float x_intercept = from.x; //Calculating the x_intercept
        for(int y = plot_y_from.y; y <= plot_y_to.y; y++) {
            Point_2D plot_y = {x_intercept+42, (-y)+36}; //Assigning them to a Plot_2D variable and transforming so the centre of the screen is 0,0
            for(int y_add = 0; y_add < height; y_add++) { //To differentiate it from a line, 'heigh' number of pixels above the line are also drawn.  This gives the impression of height
                LCD.setPixel(plot_y.x, plot_y.y - y_add, true); //Plotting the point
            }
        }

    }
}

//--------------------
//  DRAW BOOST PLATE
//--------------------

void Graphics::Graphics_Draw_Boost_Plate(Triangle_2D boost_plate, Point_2D translation, int angle, float squish, N5110 &LCD) //Draws a boost plate on the track
{
    //Using the given coordinates, calculates the points of all corners of the boost plate
    Point_2D boost_plate_TL = boost_plate.TL;
    Point_2D boost_plate_TR = {boost_plate.BR.x, boost_plate.TL.y};
    Point_2D boost_plate_BL = {boost_plate.TL.x, boost_plate.BR.y};
    Point_2D boost_plate_BR = boost_plate.BR;
    Point_2D boost_plate_mid; //The coordinate of the point of the arrow of the boost plate
    //The type defines the direction the plate is facing, e.g. Noth, South, East, West
    if(boost_plate.Type == 1) {
        //Calculates the coordinate of the point of the arrow drawn on the boost plate
        boost_plate_mid.x = boost_plate_BR.x;
        boost_plate_mid.y = (((boost_plate_TL.y - boost_plate_BR.y) / 2) + boost_plate_BR.y);
    } else if(boost_plate.Type == 2) {
        //Calculates the coordinate of the point of the arrow drawn on the boost plate
        boost_plate_mid.x = (((boost_plate_BR.x - boost_plate_TL.x) / 2) + boost_plate_TL.x);
        boost_plate_mid.y = boost_plate_BR.y;
    } else if(boost_plate.Type == 3) {
        //Calculates the coordinate of the point of the arrow drawn on the boost plate
        boost_plate_mid.x = boost_plate_TL.x;
        boost_plate_mid.y = (((boost_plate_TL.y - boost_plate_BR.y) / 2) + boost_plate_BR.y);
    } else if(boost_plate.Type == 4) {
        //Calculates the coordinate of the point of the arrow drawn on the boost plate
        boost_plate_mid.x = (((boost_plate_BR.x - boost_plate_TL.x) / 2) + boost_plate_TL.x);
        boost_plate_mid.y = boost_plate_TL.y;
    }

    //Translation
    boost_plate_TL = Translate_Point(boost_plate_TL, Round(translation.x), Round(translation.y));
    boost_plate_TR = Translate_Point(boost_plate_TR, Round(translation.x), Round(translation.y));
    boost_plate_BL = Translate_Point(boost_plate_BL, Round(translation.x), Round(translation.y));
    boost_plate_BR = Translate_Point(boost_plate_BR, Round(translation.x), Round(translation.y));
    boost_plate_mid = Translate_Point(boost_plate_mid, Round(translation.x), Round(translation.y));

    //Rotation
    boost_plate_TL = Rotate_Point(boost_plate_TL, angle);
    boost_plate_TR = Rotate_Point(boost_plate_TR, angle);
    boost_plate_BL = Rotate_Point(boost_plate_BL, angle);
    boost_plate_BR = Rotate_Point(boost_plate_BR, angle);
    boost_plate_mid = Rotate_Point(boost_plate_mid, angle);

    //Squish
    boost_plate_TL = Squish_Point(boost_plate_TL, squish);
    boost_plate_TR = Squish_Point(boost_plate_TR, squish);
    boost_plate_BL = Squish_Point(boost_plate_BL, squish);
    boost_plate_BR = Squish_Point(boost_plate_BR, squish);
    boost_plate_mid = Squish_Point(boost_plate_mid, squish);

    //Draws the square edge of the boost plate
    Graphics_Draw_Line(boost_plate_TL, boost_plate_TR, true, LCD);
    Graphics_Draw_Line(boost_plate_TR, boost_plate_BR, true, LCD);
    Graphics_Draw_Line(boost_plate_BR, boost_plate_BL, true, LCD);
    Graphics_Draw_Line(boost_plate_BL, boost_plate_TL, true, LCD);

    //For each type of boost plate draw the arrow
    if(boost_plate.Type == 1) {
        Graphics_Draw_Line(boost_plate_TL, boost_plate_mid, true, LCD);
        Graphics_Draw_Line(boost_plate_BL, boost_plate_mid, true, LCD);
    } else if(boost_plate.Type == 2) {
        Graphics_Draw_Line(boost_plate_TL, boost_plate_mid, true, LCD);
        Graphics_Draw_Line(boost_plate_BL, boost_plate_mid, true, LCD);
    } else if(boost_plate.Type == 3) {
        Graphics_Draw_Line(boost_plate_TR, boost_plate_mid, true, LCD);
        Graphics_Draw_Line(boost_plate_BR, boost_plate_mid, true, LCD);
    } else if(boost_plate.Type == 4) {
        Graphics_Draw_Line(boost_plate_TR, boost_plate_mid, true, LCD);
        Graphics_Draw_Line(boost_plate_BR, boost_plate_mid, true, LCD);
    }

}