Josh Davy / Mbed OS Flip_OS_5

Dependencies:   el17jd

Level/Level.cpp

Committer:
joshdavy
Date:
2019-05-06
Revision:
13:32d580b3935c
Parent:
11:db27d3838514
Child:
16:13044188dcc3

File content as of revision 13:32d580b3935c:

#include "Level.h"



/**
* @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);

}