Josh Davy / Mbed OS Flip_OS_5

Dependencies:   el17jd

Level/Level.cpp

Committer:
joshdavy
Date:
2019-05-06
Revision:
11:db27d3838514
Parent:
10:58cf89dd878c
Child:
13:32d580b3935c

File content as of revision 11:db27d3838514:

#include "Level.h"
/** Level Class

@brief Class responsible for the handling of levels loading them updating
their state and rendering them.
Levels represent each stage of the game including the player initial location
the goal location and the location of blocks and moving blocks.
@version 1.0

@author Joshua Davy el17jd

@date April 2019

*/



/**
* @brief Constructor (no paramateters)
*/
Level::Level() {}

/**
* @brief Deconstructor
*/
Level::~Level() {}


/** 
* @brief Initaliser. Loads the level it is passed. See LevelDefinitions for
* the format of the structs.
* @param Block blocks [] @details The array of blocks.
* @param int number_of_blocks @details The number of blocks
* @param Vector2D goal @details Location of the goal
* @param MovingBlockDefiniton moving_blocks [] @details Array of moving block
* definitions.
* @param int number_of_moving_blocks @details Number of moving blocks.
*/
void Level::init(Block blocks [],
                 int number_of_blocks,
                 Vector2D goal,
                 MovingBlockDefinition moving_blocks[],
                 int number_of_moving_blocks)
{
    // Store in private members
    _number_of_blocks = number_of_blocks;
    _goal = goal;
    for (int i = 0; i<_number_of_blocks; i++) {
        _blocks[i] = blocks[i];
    }

    // Each MovingBlockDefintion is given to the MovingBlock object array.
    // MovingBlock Struct is very similar to its defintion but stores the
    // current position and initial position of the block. 
    _number_of_moving_blocks = 0;
    for (int j = 0; j < number_of_moving_blocks; j++) {
        MovingBlockDefinition x = moving_blocks[j];
        declare_moving_block(x.index,x.extending,x.distance);
    }
}

/**
* @brief Returns a pointer to the blocks array
* @returns The blocks array
*/
Block * Level::get_blocks()
{
    return _blocks;
}

/**
* @brief Returns number of blocks
* @returns number of blocks
*/
int Level::get_number_of_blocks()
{
    return _number_of_blocks;
}

/**
* @brief Returns goal location
* @returns Vector2D of goal location
*/
Vector2D Level::get_goal()
{
    return _goal;
}


/**
* @brief Updates the location of the moving blocks. Should be called every
* frame.
*/
void Level::update_moving_blocks()
{
    // For every block
    for (int i = 0; i < _number_of_moving_blocks; i++) {
        
        // If in the extending state
        if (_moving_blocks[i].extending) {
            // Move the block to the right
            _blocks[_moving_blocks[i].index].first.x += 1;
            _blocks[_moving_blocks[i].index].second.x += 1;
        // Else its in the retracting state
        } else  {
            // So move the block to the left.
            _blocks[_moving_blocks[i].index].first.x -= 1;
            _blocks[_moving_blocks[i].index].second.x -= 1;
            }
        
        // If the blocks location is past the distance it should extend
        if (_blocks[_moving_blocks[i].index].first.x >
            _moving_blocks[i].initial_pos + _moving_blocks[i].distance) {
            // then change to the retracting state
            _moving_blocks[i].extending = false;
        }
        // If the block has retracted passed its initial position
        if (_blocks[_moving_blocks[i].index].first.x <
             _moving_blocks[i].initial_pos) {
            // then change to the extending state.
            _moving_blocks[i].extending = true;

        }

    }



}

/**
* @brief Declares a moving block
* @param int index @details The index in the block array of the block in which
* you want to move.
* @param bool extending @details If true the block begins in the extending phase
* if false then it begins in the retracting phase.
* @param int distance @details The distance to extend.
*/
void Level::declare_moving_block(int index,bool extending,int distance)
{
    MovingBlock new_moving_block;
    new_moving_block.index = index;
    new_moving_block.distance = distance;
    new_moving_block.extending = extending;
    // The top left coord is used for tracking the location of block
    new_moving_block.initial_pos = _blocks[index].first.x;
    
    // If beginning in the retracting state then move the block to its most 
    // extended state.
    if(!extending) {
        _blocks[index].first.x += distance;
        _blocks[index].second.x += distance;
    }
    
    // Add to the array and increment the number of declared moving blocks.
    _moving_blocks[_number_of_moving_blocks] = new_moving_block;
    _number_of_moving_blocks += 1;


}
/**
* @brief Renders the frame on the lcd.
* @param lcd @details The N5110 lcd object.
*/
void Level::render(N5110 &lcd)
{
    // For every block
    for (int i = 0; i<_number_of_blocks; i++) {
        // Draw a rectangle 
        lcd.drawRect(_blocks[i].first.x,_blocks[i].first.y,
                     _blocks[i].second.x - _blocks[i].first.x, // X distance
                     _blocks[i].second.y - _blocks[i].first.y, // Y distance
                     FILL_BLACK);
    }
    // Draw the goal
    lcd.drawSprite(_goal.x,_goal.y,11,6,(int *) goalMap);

}