ELEC2645 (2018/19) / Mbed 2 deprecated el17dtt

Dependencies:   mbed

GameEngine/engine.cpp

Committer:
batJoro
Date:
2019-05-10
Revision:
12:bc9a43f56261
Parent:
11:0e6a221ad8a9

File content as of revision 12:bc9a43f56261:


#include "engine.h"

Engine::Engine(){    
    
}

Engine::~Engine(){
    
}

void Engine::init(int screenHeight, int screenWidth, int speed){

    _screen_height = screenHeight;
    _screen_width = screenWidth;
    
    // set the car parameters to 0.0f
    car.set_speed(0.0f);
    car.set_car_position(0.0f);
    car.set_car_distance(0.0f);
    car.set_gear(); // this one starts from 1
    
    // road curvature is 0.0 i.e it is in the middle (straight line)
    _curvature = 0.0f;
    
    // set map fields to 0.0 as well
    map.set_player_curvature(0.0f);
    map.set_timed_curvature(0.0f); 
    
    // some variables to keep details of the current map and time 
    _track_distance = 0.0f;
    _lap_time = 0.0f;
    
    
    // design a map
    addSegment(0.0f, 500.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(1.0f, 600.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(1.0f, 140.0f);
    addSegment(-1.0f, 150.0f);
    addSegment(1.0f, 600.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(1.0f, 200.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(0.0f, 500.0f);
    addSegment(-1.0f, 600.0f);
    addSegment(1.0f, 200.0f);
    addSegment(1.0f, 140.0f);
    addSegment(-1.0f, 50.0f);
    addSegment(1.0f, 140.0f);
    addSegment(-1.0f, 150.0f);
    addSegment(0.0f, 700.0f);
    
    // find how long is the track 
    calc_track_distance();
     
}


void Engine::update(Gamepad &pad, N5110 &lcd, float elapsedTime) {
    
    // split the curvature do it appears slowly
    if(fabs(map.get_player_curvature() - map.get_timed_curvature()) >= 0.5f) {
            
            car.set_speed(car.get_speed() - 5.0f * elapsedTime);  
    }
        
    
    // how the car perceives the track
    car.set_car_distance(car.get_car_distance() + 
                        (car.get_speed() * 300.0f) * elapsedTime * car.get_rev());
    
    // get point on track 
    float foffset = 0;
    int ntrackSection = 0;
    
    // add the time to the overall time
    _lap_time += elapsedTime;
    
    // restart the car distance 
    if ( car.get_car_distance() >= _track_distance) {
        car.set_car_distance(car.get_car_distance() - _track_distance);
        _lap = 1;
    }
 
    // find position on track
    while( ntrackSection < track.size() && foffset < car.get_car_distance()){
     
        foffset += track[ntrackSection].meters;
        ntrackSection++; 
    }
    
    // the curvature of the segment we are in
    float targetCurvature = track[ntrackSection -1].curvature;
    
    // small curvature to be displayed but this time based on speed as well
    float curvDiff = (targetCurvature - _curvature) * elapsedTime * car.get_speed();
     // slowly changing curvature
    _curvature += curvDiff;

    // the best curvature we should aim for
    // other wise the car gets slowed down
    map.set_timed_curvature( (_curvature) * elapsedTime * car.get_speed() );
    

    // draw car 
    car.set_car_position(map.get_player_curvature() - map.get_timed_curvature());  
     
}

void Engine::read_input(Gamepad &pad, float elapsedTime) {
    
    float _mag;
    _mag = pad.get_mag();
    
    // car moving to the front 
    if(pad.get_direction() == N) {
            car.set_speed(car.get_speed() + 0.5f * elapsedTime * _mag);
            car.set_direction(0); // 
    }
    else {
            car.set_speed(car.get_speed() - 1.8f * elapsedTime); 
    }
    
    // car brake
    if(pad.get_direction() == S) {
            car.set_speed(car.get_speed() - 5.0f * elapsedTime * _mag);
            car.set_direction(0); // 
    }
    
    // car moving to the diagonally    
    if(pad.get_direction() == W || pad.get_direction() == NW) {
            if(pad.get_direction() == NW) {
                map.set_player_curvature(map.get_player_curvature() - 0.7f * elapsedTime);
                car.set_speed(car.get_speed() + 4.5f * elapsedTime * _mag);
            }
            else 
                map.set_player_curvature(map.get_player_curvature() - 1.4f * elapsedTime);
            car.set_direction(1);
            
    }
    // car moving to the diagonally  
    if(pad.get_direction() == E || pad.get_direction() == NE) {
            if(pad.get_direction() == NE) {
                map.set_player_curvature(map.get_player_curvature() + 0.7f * elapsedTime);
                car.set_speed(car.get_speed() + 4.5f * elapsedTime * _mag);
            } 
            else    
                map.set_player_curvature(map.get_player_curvature() + 1.4f * elapsedTime);
            car.set_direction(2);
    }
    
    // change gears
    if(pad.check_event(Gamepad::Y_PRESSED)) {
        car.upShift();   
    }
    if(pad.check_event(Gamepad::X_PRESSED)) {
        car.downShift();   
    }
}
 
// draw the road and the sides we only need half the screen 
void Engine::draw(N5110 &lcd) {

    for (int y = 0; y < _screen_height / 2; y++) {
            
        float fPerspective = (float)y / (_screen_height / 2.0f);
        
        for (int x = 0; x < _screen_width; x++) {
            
            float fPointCentre = 0.5f + _curvature * powf((1.0f - fPerspective), 3);
            float fRoadSpace = 0.1f + fPerspective * 0.8f;
            float fSideSpace = fRoadSpace * 0.15f;
            
            // for easier calculating the sides spliting the road space in two
            fRoadSpace *= 0.5f;
            
            int leftGrass = (fPointCentre - fRoadSpace - fSideSpace) * _screen_width;
            int leftSide = (fPointCentre - fRoadSpace) * _screen_width;
            int rightGrass = (fPointCentre + fRoadSpace + fSideSpace) * _screen_width;
            int rightSide = (fPointCentre + fRoadSpace) * _screen_width;
            
            int row = _screen_height / 2 + y;
            
            float GrassColour = defineStripes(lcd, car, 20.0f, fPerspective);          
            float SideColour = defineStripes(lcd, car, 40.0f, fPerspective);
            
            assignPixel(lcd, x, y, row, SideColour, GrassColour, leftGrass, rightGrass,
                                                                leftSide,
                                                                rightSide);       
        }
        car.draw(lcd, 84);
        drawFrame(lcd); // draw the frame around the picture
        
    }
}
// colour the pixel accoring to the give boundaries
void Engine::assignPixel(N5110 &lcd,int x, int y, int row, float SideColour, float GrassColour,
                                                                int leftGrass,
                                                                int rightGrass,
                                                                int leftSide,
                                                                int rightSide) {
            if ( x >= 0 && x < leftGrass) {
                if ( GrassColour == 0.0f ) 
                lcd.setPixel(x, row, true);
            } 
            if ( x >= leftGrass && x < leftSide) {
                if ( x % 2 ==0)
                    if ( SideColour == 0.0f ) 
                        lcd.setPixel(x, row, true);
            }
            if ( x >= rightSide && x < rightGrass ) {
                if ( x % 2 ==0)
                     if ( SideColour == 0.0f ) 
                        lcd.setPixel(x, row, true);
            } 
            if ( x >= rightGrass && x < _screen_width) {
                if ( GrassColour == 0.0f ) 
                lcd.setPixel(x, row, true);
            }
} 

// use sin function to 'paint' the grass
float Engine::defineStripes(N5110 &lcd, Car &car, float frequency, float perspective) {
    
    float colour = sinf(frequency * powf(1.0f - perspective, 3) + car.get_car_distance() * 0.1f);
    
    if (colour > 0.0f) colour = 1.0f;
    else colour = 0.0f;
    
    return colour;
}
// add segment to the map
void Engine::addSegment(float curvature, float meters) {
    
    // clap the curvature variable
    if(curvature < -1.0f) curvature = -1.0f;
    if(curvature > 1.0f) curvature = 1.0f;
    // place a segment on the map
    MapSegment segment;
    segment.curvature = curvature;
    segment.meters = meters;
    track.push_back(segment);   
}

// go throught the map and add distance
void Engine::calc_track_distance() {
    
    for (vector<MapSegment>::iterator it = track.begin(); it != track.end(); ++it) {
        _track_distance += it->meters;
    }
}

int Engine::get_lap() {
     
     return _lap;
    }
    
float Engine::get_lap_time() {
    
     return _lap_time;
    }