Henry Triff / Mbed 2 deprecated ELEC2645_Project_el18ht

Dependencies:   mbed

Mechanics/Mechanics.cpp

Committer:
HenryWTriff
Date:
2020-03-28
Revision:
20:f8d7b04471b8
Parent:
11:7b12992156de
Child:
25:31761087a83f

File content as of revision 20:f8d7b04471b8:

#include "Mechanics.h"

//--------------------------------
//  CONSTRUCTORS AND DESTRUCTORS
//--------------------------------

Mechanics::Mechanics()
{
}

Mechanics::~Mechanics()
{
}

//---------
//  SPEED
//---------

float Mechanics::Get_Speed(float speed, float max_speed, float acceleration, float deceleration,  float off_track_speed, Point_2D position, const Square_2D *offtrack_square, const Triangle_2D *offtrack_triangle, const Square_2D *out_of_bounds_square, const Triangle_2D *out_of_bounds_triangle, const Triangle_2D *plates, const Map_Data map_info, Gamepad &Device)
{
    bool offtrack = Is_Offtrack(position, offtrack_square, offtrack_triangle, map_info);
    bool out_of_bounds = Is_Out_Of_Bounds(position, out_of_bounds_square, out_of_bounds_triangle,  map_info);

    if(Device.X_held() == true && Device.A_held() == false) { //If accelerator is pressed and break is not
        if(speed >= 0 && speed < max_speed) { //If the speed is greater than 0 and less than max speed
            speed += acceleration; //Increase the speed
        } else if(speed < 0) { //If the speed is less than 0
            speed = 0; //Set speed to 0
        }
    } else if(Device.A_held() == true && Device.X_held() == false) { //If the break is pressed and accelerator is not
        if(speed > 0) { //If speed is greater than 0
            speed -= deceleration; //Decrease the speed
        } else if(speed <= 0) { //If speed is less than 0
            speed = -1; //Set speed to -1
        }
    } else if(Device.A_held() == false && Device.X_held() == false) { //If no button is pressed
        if(speed > 0) { //If speed is greater than 0
            speed -= 0.05; //Decrease speed gradually
        } else { //If speed is less than zero
            speed = 0; //Set speed to 0
        }
    }
    if(offtrack == true) { //If the car is offtrack
        if(speed > off_track_speed) { //If speed is greater than off track speed
            speed -= 0.10; //Speed is rapidly reduced
        }
    }

    speed = Get_Boost_Speed(plates, map_info.number_of_boost_plates, position, speed); //If the car is on a boost plate change the speed

    //printf("%f\n", speed);

    return speed; //Return the speed
}

//-----------------------------------
//  OFF TRACK / OUT OF BOUNDS CHECK
//-----------------------------------

//COMBINING
bool Mechanics::Is_Offtrack(Point_2D position, const Square_2D offtrack_square[], const Triangle_2D offtrack_triangle[], const Map_Data map_info) //Check to see if the player is off track
{
    return (Is_Offtrack_Square(offtrack_square, map_info.number_of_off_track_squares, position) || Is_Offtrack_Triangle(offtrack_triangle, map_info.number_of_off_track_triangles, position));//Return the result of checking squares and triangles
}

bool Mechanics::Is_Out_Of_Bounds(Point_2D position, const Square_2D out_of_bounds_square[], const Triangle_2D out_of_bounds_triangle[], const Map_Data map_info) //Check to see if the player is out of bounds
{
    return (Is_Out_Of_Bounds_Square(out_of_bounds_square, map_info.number_of_out_of_bounds_squares, position) || Is_Out_Of_Bounds_Triangle(out_of_bounds_triangle, map_info.number_of_out_of_bounds_triangles, position)); //Return the result of checking squares and triangles
}


//  OFF TRACK
bool Mechanics::Is_Offtrack_Square(const Square_2D offtrack[], int size, Point_2D position)
{
    for(int i = 0; i < size; i++) { //Iterate through the offtrack array
        if(position.x > offtrack[i].TL.x && position.x < offtrack[i].BR.x && position.y < offtrack[i].TL.y && position.y > offtrack[i].BR.y ) { //If the position of the car is in the out_of_bounds square
            return true; //return that the car is off track
        }
    }
    return false; //return that the car is NOT off track
}

bool Mechanics::Is_Offtrack_Triangle(const Triangle_2D offtrack[], int size, Point_2D position)
{
    for(int i = 0; i < size; i++) { //Iterate through the offtrack array
        if(position.x > offtrack[i].TL.x && position.x < offtrack[i].BR.x && position.y < offtrack[i].TL.y && position.y > offtrack[i].BR.y ) { //If the player is in the square area of the off track triangle
            if(offtrack[i].Type == 1) { //If the direction of the triangle is type 1 = Hypotenuse is on the top right
                Point_2D Translated_position = {position.x - offtrack[i].TL.x, position.y - offtrack[i].TL.y}; //Compare the position of the car to the top left position of the triangle
                float position_limit = (offtrack[i].BR.y - offtrack[i].TL.y) / (offtrack[i].BR.x - offtrack[i].TL.x) * Translated_position.x;  //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y < position_limit) { //If the y position of the car is less than the y position limit
                    return true; //Return that the car is off track
                }
            } else if(offtrack[i].Type == 2) { //If the direction of the triangle is type 1 = Hypotenuse is on the bottom right
                Point_2D Translated_position = {position.x - offtrack[i].TL.x, position.y - offtrack[i].BR.y}; //Compare the position of the car to the top bottom position of the triangle
                float position_limit =  (offtrack[i].TL.y - offtrack[i].BR.y) / (offtrack[i].BR.x - offtrack[i].TL.x) * Translated_position.x;  //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y > position_limit) { //If the y position of the car is greater than the y position limit
                    return true; //Return that the car is off track
                }
            } else if(offtrack[i].Type == 3) { //If the direction of the triangle is type 1 = Hypotenuse is on the bottom left
                Point_2D Translated_position = {position.x - offtrack[i].TL.x, position.y - offtrack[i].TL.y}; //Compare the position of the car to the top bottom position of the triangle
                float position_limit = (offtrack[i].BR.y - offtrack[i].TL.y) / (offtrack[i].BR.x - offtrack[i].TL.x) * Translated_position.x;  //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y > position_limit) { //If the y position of the car is greater than the y position limit
                    return true; //Return that the car is off track
                }
            } else if(offtrack[i].Type == 4) { //If the direction of the triangle is type 1 = Hypotenuse is on the top left
                Point_2D Translated_position = {position.x - offtrack[i].TL.x, position.y - offtrack[i].BR.y}; //Compare the position of the car to the top left position of the triangle
                float position_limit =  (offtrack[i].TL.y - offtrack[i].BR.y) / (offtrack[i].BR.x - offtrack[i].TL.x) * Translated_position.x;  //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y < position_limit) { //If the y position of the car is less than the y position limit
                    return true; //Return that the car is off track
                }
            }
        }
    }
    return false; //Return that the car is NOT off track
}

//  OUT OF BOUNDS
bool Mechanics::Is_Out_Of_Bounds_Square(const Square_2D out_of_bounds[], int size, Point_2D position)
{
    for(int i = 0; i < size; i++) { //Iterate through the out_of_bounds array
        if(position.x > out_of_bounds[i].TL.x && position.x < out_of_bounds[i].BR.x && position.y < out_of_bounds[i].TL.y && position.y > out_of_bounds[i].BR.y ) { //If the position of the car is in the out_of_bounds square
            return true; //return that the car is out of bounds
        }
    }
    return false; //return that the car is NOT out of bounds
}

bool Mechanics::Is_Out_Of_Bounds_Triangle(const Triangle_2D out_of_bounds[], int size, Point_2D position) //Calculate if the player is out of bounds when compared to triangular out of bounds
{
    for(int i = 0; i < size; i++) { //Iterate through the out_of_bounds array
        if(position.x > out_of_bounds[i].TL.x && position.x < out_of_bounds[i].BR.x && position.y < out_of_bounds[i].TL.y && position.y > out_of_bounds[i].BR.y ) { //If the player is in the square area of the out of bounds triangle
            if(out_of_bounds[i].Type == 1) { //If the direction of the triangle is type 1 = Hypotenuse is on the top right
                Point_2D Translated_position = {position.x - out_of_bounds[i].TL.x, position.y - out_of_bounds[i].TL.y}; //Compare the position of the car to the top left position of the triangle
                float position_limit = (out_of_bounds[i].BR.y - out_of_bounds[i].TL.y) / (out_of_bounds[i].BR.x - out_of_bounds[i].TL.x) * Translated_position.x; //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y < position_limit) { //If the y position of the car is less than the y position limit
                    return true; //Return that the car is out of bounds
                }
            } else if(out_of_bounds[i].Type == 2) { //If the direction of the triangle is type 2 = Hypotenuse is on the bottom right
                Point_2D Translated_position = {position.x - out_of_bounds[i].TL.x, position.y - out_of_bounds[i].BR.y}; //Compare the position of the car to the bottom left position of the triangle
                float position_limit =  (out_of_bounds[i].TL.y - out_of_bounds[i].BR.y) / (out_of_bounds[i].BR.x - out_of_bounds[i].TL.x) * Translated_position.x; //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y > position_limit) {  //If the y position of the car is greater than the y position limit
                    return true; //Return that the car is out of bounds
                }
            } else if(out_of_bounds[i].Type == 3) { //If the direction of the triangle is type 3 = Hypotenuse is on the bottom left
                Point_2D Translated_position = {position.x - out_of_bounds[i].TL.x, position.y - out_of_bounds[i].TL.y}; //Compare the position of the car to the top left position of the triangle
                float position_limit = (out_of_bounds[i].BR.y - out_of_bounds[i].TL.y) / (out_of_bounds[i].BR.x - out_of_bounds[i].TL.x) * Translated_position.x; //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y > position_limit) {  //If the y position of the car is greater than the y position limit
                    return true; //Return that the car is out of bounds
                }
            } else if(out_of_bounds[i].Type == 4) { //If the direction of the triangle is type 1 = Hypotenuse is on the top left
                Point_2D Translated_position = {position.x - out_of_bounds[i].TL.x, position.y - out_of_bounds[i].BR.y}; //Compare the position of the car to the bottom left position of the triangle
                float position_limit =  (out_of_bounds[i].TL.y - out_of_bounds[i].BR.y) / (out_of_bounds[i].BR.x - out_of_bounds[i].TL.x) * Translated_position.x; //Calculate the y coordinate of the hypotenuse of the triangle at the given x position
                if(Translated_position.y < position_limit) {  //If the y position of the car is less than the y position limit
                    return true; //Return that the car is out of bounds
                }
            }
        }
    }
    return false;  //Return that the car is NOT out of bounds
}

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

float Mechanics::Get_Boost_Speed(const Triangle_2D plates[], int number_of_plates, Point_2D position, float speed) //If the player is on a boost plate
{
    for(int i = 0; i < number_of_plates; i++) { //Iterate through all boost plates
        if(position.x > plates[i].TL.x && position.x < plates[i].BR.x && position.y < plates[i].TL.y && position.y > plates[i].BR.y) { //If the player is in a boost plate
            speed = 8; //Increase the players speed to 8
        }
    }
    return speed; //Return the speed
}

//------------------
//  GATES AND LAPS
//------------------

int Mechanics::Get_Gate(const Square_2D gates[], int number_of_gates, Point_2D position, int current_gate)
{
    int next_gate;

    if(current_gate + 1 <= (number_of_gates - 1)) { //If the current gate is not the last in the array
        next_gate = current_gate + 1; //The next gate is the current gate + 1
    } else { //Else if it is the last gate in the array
        next_gate = 0; //Then the next gate is 0
    }

    if(position.x >= gates[next_gate].TL.x && position.x <= gates[next_gate].BR.x && position.y <= gates[next_gate].TL.y && position.y >= gates[next_gate].BR.y) { //Check if the players position is in the next gate
        return next_gate; //Return the current gate as being the next one
    }

    return current_gate; //Else if the player has not yet reached the next gate, then the current gate remains the same
}

int Mechanics::Get_Laps(int laps, const Square_2D gates[], int number_of_gates, Point_2D position, int current_gate) //Calculate the number of laps
{
    int next_gate;

    if(current_gate + 1 <= (number_of_gates - 1)) { //If the current gate is not the last in the array
        next_gate = current_gate + 1; //The next gate is the current gate + 1
    } else { //Else if it is the last gate in the array
        next_gate = 0; //Then the next gate is 0
    }
    if(position.x >= gates[next_gate].TL.x && position.x <= gates[next_gate].BR.x && position.y <= gates[next_gate].TL.y && position.y >= gates[next_gate].BR.y) {
        if(next_gate == 0) { //If the car is in the area of the next gate and the next gate is 0
            laps++; //Increase the number of laps
        }
    }
    return laps; //Return the number of laps
}

//--------
//  TIME
//--------

Time Mechanics::Convert_To_Time(int game_fps, int number_of_frames) //Convert The number of frames elapsed to minutes, seconds and miliseconds
{
    int total_seconds = float(number_of_frames) / float(game_fps); //Calculate the total number of seconds elapsed
    int seconds = total_seconds % 60; //The remainder after 60 is the seconds
    float miliseconds_decimal = (float(number_of_frames) / float(game_fps)) - seconds; //Calculating the decimal number of miliseconds
    int miliseconds = float(miliseconds_decimal * 1000); //Multiplying by 1000 to get the number of miliseconds as an integer
    int minuites = (total_seconds - seconds) / 60; //The minutes is the total number of seconds subtract the seconds on the clock divided by 60
    return {minuites, seconds, miliseconds}; //Return the time
}

//-------------
//  GET ANGLE
//-------------

int Mechanics::Get_Angle(int angle, int handling, bool gyro_enabled, FXOS8700CQ &Gyro, Gamepad &Device)
{
    if(gyro_enabled == false) { //If we are using stick control
        int Stick_Position = Device.get_direction(); //The stick position is calculated
        float Stick_Magnitude = Device.get_mag(); //The magnitude of the stick position is calculated
        if(Stick_Magnitude > 0.95) { //Rounds up if almost at full magnitude
            Stick_Magnitude = 1;
        }
        if(Stick_Position == E || Stick_Position == NE || Stick_Position == SE) { //Allows the stick to be pushed in any right direction
            angle += handling * Stick_Magnitude; //The angle is increased by the handling of the car × stick magntude
        } else if(Stick_Position == W || Stick_Position == NW || Stick_Position == SW) { //Allows the stick to be pushed in any left direction
            angle -= handling * Stick_Magnitude; //The angle is decreased by the handling of the car × stick magntude
        }
        return angle; //Return the new angle of rotation of the track
    } else {
        Gyro_Data Gyro_Tilt = Gyro.get_values(); //Calculate the amount of tilt of the device
        float tilt = Gyro_Tilt.ay * 90; //Turn the tild into an angle from -90° to +90°
        if(tilt > 5) { //±5° deadzone
            if(tilt < 40) { //Max angle is 40°
                angle += handling * (tilt/40); //Increase the angle
            } else {
                angle += handling; //Increase the angle
            }
        } else if(tilt < -5) {//±5° deadzone
            if(tilt > -40) { //Max angle is -40°
                angle -= handling * (tilt/-40); //Decrease the angle
            } else {
                angle -= handling; //Decrease the angle
            }
        }
        return angle; //Return the new angle of roation of the track
    }
}

//-------------------
//  GET TRANSLATION
//-------------------

Point_2D Mechanics::Get_Translation(Point_2D in, float angle, float speed, const Square_2D *out_of_bounds_square, const Triangle_2D *out_of_bounds_triangle, const Map_Data map_info, Gamepad &Device)
//Calculates the change in the translation of the map, depending on the speed and direction of the cars movement
{
    float temp_speed;

    //Converting to floats
    float x = in.x;
    float y = in.y;

    //Checking to see if the car is out of bounds
    bool out_of_bounds = Is_Out_Of_Bounds(in, out_of_bounds_square, out_of_bounds_triangle,  map_info);
    if(out_of_bounds == true) {
        if(speed > 0) { //If the car is driving forward
            temp_speed = -4; //The speed is temporarily reversed
        } else if(speed < 0) { //If the car is driving backward
            temp_speed = 4; //The speed is temporarily forward
        }
        y += temp_speed * cos(-angle * PI / 180); //The change in the y position is then claculated
        x -= temp_speed * sin(-angle * PI / 180); //The change in the x position is then calculated
    }
    //printf("%f\n", temp_speed);
    y += speed * cos(-angle * PI / 180); //The change in the x position is then claculated
    x -= speed * sin(-angle * PI / 180); //The change in the y position is then claculated

    return {x,y};
}

//-----------------------------
//  CAR MODELS AND PARAMETERS
//-----------------------------

float Mechanics::Get_Max_Speed(int car_model) //Returns the maximum speed of each vehicle
{
    //For each car, Return the maximum speed when on track
    //This is the number of integer coordinates in any direction moved by the car per frame
    if(car_model == Stupid) {
        return 8;
    } else if(car_model == Racecar) {
        return 6;
    } else if(car_model == Sportscar) {
        return 4;
    } else if(car_model == Drifter) {
        return 4;
    } else if(car_model == Offroad) {
        return 2;
    } else if(car_model == Basic) {
        return 3;
    }
}

float Mechanics::Get_Acceleration(int car_model) //Returns the acceleration of each vehicle
{
    //For each car, Return the acceleration when accelerating
    //This is the rate of change in the number of integer coordinates in any direction moved by the car per frame
    if(car_model == Stupid) {
        return 0.15;
    } else if(car_model == Racecar) {
        return 0.1;
    } else if(car_model == Sportscar) {
        return 0.08;
    } else if(car_model == Drifter) {
        return 0.05;
    } else if(car_model == Offroad) {
        return 0.02;
    } else if(car_model == Basic) {
        return 0.03;
    }

}

float Mechanics::Get_Deceleration(int car_model) //Returns the deceleration when the brakes are pressed for each vehicle
{
    //For each car, Return the deceleration when breaking
    //This is the rate of change in the number of integer coordinates in any direction moved by the car per frame
    if(car_model == Stupid) {
        return 0.3;
    } else if(car_model == Racecar) {
        return 0.15;
    } else if(car_model == Sportscar) {
        return 0.1;
    } else if(car_model == Drifter) {
        return 0.03;
    } else if(car_model == Offroad) {
        return 0.03;
    } else if(car_model == Basic) {
        return 0.05;
    }
}

float Mechanics::Get_Off_Road_Speed(int car_model) //Returns the maximum speed that the vehicle can travel off road
{
    //For each car, Return the max speed when off road
    //This is the number of integer coordinates in any direction moved by the car per frame
    if(car_model == Stupid) {
        return 2;
    } else if(car_model == Racecar) {
        return 0.5;
    } else if(car_model == Sportscar) {
        return 0.8;
    } else if(car_model == Drifter) {
        return 0.3;
    } else if(car_model == Offroad) {
        return 2;
    } else if(car_model == Basic) {
        return 0.8;
    }
}

int Mechanics::Get_Handling(int car_model) //Returns the value for the handling of each vehicle
{

    //For each car, return the handling
    //Handling is the change is the max degrees of rotation of track per frame
    if(car_model == Stupid) {
        return 3;
    } else if(car_model == Racecar) {
        return 3;
    } else if(car_model == Sportscar) {
        return 2;
    } else if(car_model == Drifter) {
        return 2;
    } else if(car_model == Offroad) {
        return 1;
    } else if(car_model == Basic) {
        return 2;
    }
}