561 lines
12 KiB
C++
561 lines
12 KiB
C++
/* **************************************
|
|
* Includes *
|
|
* **************************************/
|
|
|
|
#include "Player.h"
|
|
#include "Pad.h"
|
|
#include <limits.h>
|
|
|
|
/* **************************************
|
|
* Defines *
|
|
* **************************************/
|
|
|
|
#define ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES 5
|
|
#define MAX_SELECTION_DIST 400
|
|
#define NO_SELECTION -1
|
|
|
|
/* **************************************
|
|
* Local variables *
|
|
* **************************************/
|
|
|
|
Player::Player(void)
|
|
{
|
|
}
|
|
|
|
Player::~Player(void)
|
|
{
|
|
|
|
}
|
|
|
|
void Player::Init(void)
|
|
{
|
|
uint8_t i;
|
|
|
|
unit_i = 0;
|
|
|
|
selectedUnitCandidate = NO_SELECTION;
|
|
|
|
CameraInit(&Camera);
|
|
UnitInit();
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
memset(&units[i], 0, sizeof(TYPE_UNIT));
|
|
}
|
|
|
|
TYPE_COLLISION_BLOCK cb;
|
|
|
|
Resources.Wood = 25;
|
|
Resources.Gold = 50;
|
|
Resources.Food = 75;
|
|
|
|
cb.x = SystemRand(0, 20);
|
|
cb.y = SystemRand(0, 20);
|
|
|
|
if (createUnit(BARRACKS, cb) == false)
|
|
{
|
|
GfxPrintText_Flash(F("Failed to create building!"));
|
|
}
|
|
|
|
cb.x = SystemRand(48, 56);
|
|
cb.y = SystemRand(48, 56);
|
|
cb.w = UnitGetWidthFromID(PEASANT);
|
|
cb.h = UnitGetHeightFromID(PEASANT);
|
|
|
|
showActionsMenu_counter = 0;
|
|
showActionsMenu_index = 0;
|
|
showActionsMenu = false;
|
|
anyUnitSelected = false;
|
|
|
|
if (createUnit(PEASANT, cb) == false)
|
|
{
|
|
GfxPrintText_Flash(F("Failed to create unit!"));
|
|
}
|
|
}
|
|
|
|
void Player::showHealth(uint8_t hp)
|
|
{
|
|
enum
|
|
{
|
|
HP_TEXT_X = 4,
|
|
HP_TEXT_Y = Y_SCREEN_RESOLUTION - 4,
|
|
};
|
|
|
|
char str[8];
|
|
|
|
GfxFillRectangle(0, Y_SCREEN_RESOLUTION - 5, X_SCREEN_RESOLUTION, 8, GFX_WHITE);
|
|
|
|
snprintf(str, sizeof(str), "HP=%u", hp);
|
|
|
|
GfxPrintTextFont(str, font3x3, HP_TEXT_X, HP_TEXT_Y);
|
|
}
|
|
|
|
void Player::DrawHandler(void)
|
|
{
|
|
enum
|
|
{
|
|
PROGRESS_BAR_X = X_SCREEN_RESOLUTION - 16,
|
|
PROGRESS_BAR_Y = Y_SCREEN_RESOLUTION - 4,
|
|
PROGRESS_BAR_W = ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES << 1,
|
|
PROGRESS_BAR_H = 3,
|
|
};
|
|
|
|
uint8_t i;
|
|
bool bAnyoneSelected = false;
|
|
|
|
//GfxRenderTiles(&Camera);
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* u = &units[i];
|
|
|
|
if (u->alive == false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bool selected = false;
|
|
|
|
if (selectedUnitCandidate != NO_SELECTION)
|
|
{
|
|
selected = (i == selectedUnitCandidate);
|
|
}
|
|
|
|
UnitDraw(u, &Camera, selected);
|
|
|
|
if ( (u->selected == true) && (bAnyoneSelected == false) )
|
|
{
|
|
bAnyoneSelected = true;
|
|
|
|
showHealth(u->hp);
|
|
}
|
|
}
|
|
|
|
if (bAnyoneSelected == true)
|
|
{
|
|
GfxDrawRectangle(PROGRESS_BAR_X, PROGRESS_BAR_Y, PROGRESS_BAR_W, PROGRESS_BAR_H, GFX_BLACK);
|
|
|
|
if (showActionsMenu_counter != 0)
|
|
{
|
|
GfxFillRectangle(PROGRESS_BAR_X, PROGRESS_BAR_Y, showActionsMenu_counter << 1, PROGRESS_BAR_H, GFX_BLACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Player::checkNewBuildingPosition(TYPE_COLLISION_BLOCK * cb)
|
|
{
|
|
uint8_t i;
|
|
TYPE_COLLISION_BLOCK bldgCB;
|
|
bool success;
|
|
static uint8_t max_tries = 0;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
success = false;
|
|
|
|
if (ptrUnit->building == false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bldgCB.x = ptrUnit->x;
|
|
bldgCB.y = ptrUnit->y;
|
|
bldgCB.w = UnitGetWidthFromID(ptrUnit->id);
|
|
bldgCB.h = UnitGetHeightFromID(ptrUnit->id);
|
|
|
|
if (SystemCollisionCheck(*cb, bldgCB) == true)
|
|
{
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
success = true;
|
|
}
|
|
|
|
if (success == false)
|
|
{
|
|
cb->x = SystemRand(0, 128);
|
|
cb->y = SystemRand(0, 128);
|
|
|
|
if (++max_tries < 16)
|
|
{
|
|
if (checkNewBuildingPosition(cb) == false)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
max_tries = 0;
|
|
return true;
|
|
}
|
|
|
|
bool Player::createUnit(TYPE_UNIT_ID id, TYPE_COLLISION_BLOCK cb)
|
|
{
|
|
if (unit_i < PLAYER_MAX_UNITS_BUILDINGS)
|
|
{
|
|
TYPE_UNIT* ptrNewUnit = &units[unit_i];
|
|
ptrNewUnit->id = id;
|
|
ptrNewUnit->x = cb.x;
|
|
ptrNewUnit->y = cb.y;
|
|
ptrNewUnit->hp = UnitGetHpFromID(id);
|
|
ptrNewUnit->alive = true;
|
|
|
|
ptrNewUnit->building = (id > MAX_UNIT_ID);
|
|
|
|
unit_i++;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
TYPE_COLLISION_BLOCK Player::GetCursorPos(void)
|
|
{
|
|
TYPE_COLLISION_BLOCK cb;
|
|
|
|
cb.x = (X_SCREEN_RESOLUTION >> 1) - 4 - Camera.X_Offset;
|
|
cb.y = (Y_SCREEN_RESOLUTION >> 1) - 4 - Camera.Y_Offset;
|
|
cb.w = 8;
|
|
cb.h = 8;
|
|
|
|
return cb;
|
|
}
|
|
|
|
void Player::UnitBuildingSelection(void)
|
|
{
|
|
uint16_t i;
|
|
uint32_t nearest_unit_dist = 0xFFFFFFFF; // Set maximum value
|
|
uint32_t dist;
|
|
|
|
int8_t nearest_unit = NO_SELECTION;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* u = &units[i];
|
|
|
|
if ( (u->alive == false) || (u->selected == true) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos();
|
|
TYPE_COLLISION_BLOCK u_cb = {u->x, u->y, UnitGetWidthFromID(u->id), UnitGetHeightFromID(u->id) };
|
|
|
|
uint16_t dist_x = (u_cb.x + (u_cb.w >> 1) - cursor_cb.x);
|
|
uint16_t dist_y = (u_cb.y + (u_cb.h >> 1) - cursor_cb.y);
|
|
|
|
dist = (dist_x * dist_x) + (dist_y * dist_y);
|
|
|
|
if (dist < nearest_unit_dist)
|
|
{
|
|
nearest_unit_dist = dist;
|
|
nearest_unit = (int8_t)i;
|
|
}
|
|
}
|
|
|
|
selectedUnitCandidate = nearest_unit;
|
|
}
|
|
|
|
void Player::ActionsMenu(void)
|
|
{
|
|
if (showActionsMenu == true)
|
|
{
|
|
for (uint8_t i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
uint8_t availableActions = UnitGetAvailableActions(ptrUnit);
|
|
|
|
if (!(availableActions & (1 << showActionsMenu_index) ) )
|
|
{
|
|
IncreaseShowActionsMenuIndex();
|
|
}
|
|
|
|
UNIT_ACTION action = (UNIT_ACTION) (showActionsMenu_index);
|
|
|
|
const char* str = UnitGetActionString(action);
|
|
|
|
GfxPrintText(str, 40, Y_SCREEN_RESOLUTION - 4);
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void Player::Handler(void)
|
|
{
|
|
CameraSetLock(&Camera, showActionsMenu);
|
|
|
|
CameraHandler(&Camera);
|
|
|
|
UnitBuildingSelection();
|
|
|
|
for (uint8_t i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
UnitHandler(ptrUnit);
|
|
}
|
|
|
|
ActionsMenu();
|
|
|
|
ButtonHandler();
|
|
|
|
GfxShowResources(&Resources);
|
|
}
|
|
|
|
void Player::ButtonHandler(void)
|
|
{
|
|
if (PadButtonPressed(PAD_A) == true)
|
|
{
|
|
ButtonAPressed();
|
|
}
|
|
else if (PadButtonReleased(PAD_A) == true)
|
|
{
|
|
ButtonAReleased();
|
|
}
|
|
else if (PadButtonPressed(PAD_B) == true)
|
|
{
|
|
ButtonBPressed();
|
|
}
|
|
else if (PadButtonReleased(PAD_B) == true)
|
|
{
|
|
ButtonBReleased();
|
|
}
|
|
else if (PadButtonReleased(PAD_LEFT) == true)
|
|
{
|
|
ButtonLeftReleased();
|
|
}
|
|
else if (PadButtonReleased(PAD_RIGHT) == true)
|
|
{
|
|
ButtonRightReleased();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void Player::ButtonAPressed(void)
|
|
{
|
|
// Only increase progress bar when any unit has been previously selected
|
|
if (anyUnitSelected == true)
|
|
{
|
|
if (showActionsMenu == false)
|
|
{
|
|
if (showActionsMenu_counter < ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES)
|
|
{
|
|
showActionsMenu_counter++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Player::ButtonAReleased(void)
|
|
{
|
|
if (showActionsMenu_counter < ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES)
|
|
{
|
|
if (selectedUnitCandidate != NO_SELECTION)
|
|
{
|
|
// When actions menu is not active, select unit if
|
|
// a candidate is present
|
|
TYPE_UNIT* ptrUnit = &units[selectedUnitCandidate];
|
|
|
|
ptrUnit->selected = true;
|
|
anyUnitSelected = true;
|
|
showActionsMenu_index = 0;
|
|
}
|
|
|
|
showActionsMenu_counter = 0;
|
|
}
|
|
else if (showActionsMenu == true)
|
|
{
|
|
uint8_t i = 0;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
if (showActionsMenu_index == ACTION_CREATE_UNIT)
|
|
{
|
|
uint8_t w = UnitGetWidthFromID(ptrUnit->id);
|
|
uint8_t h = UnitGetHeightFromID(ptrUnit->id);
|
|
uint8_t new_pos_x = ptrUnit->x + SystemRand(w, w + (w >> 1));
|
|
uint8_t new_pos_y = ptrUnit->y + SystemRand(h, h + (h >> 1));
|
|
TYPE_COLLISION_BLOCK cb = {.x = new_pos_x, .y = new_pos_y};
|
|
|
|
createUnit(PEASANT, cb);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
showActionsMenu = (showActionsMenu_counter < ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES)? false: true;
|
|
}
|
|
|
|
void Player::ButtonBPressed(void)
|
|
{
|
|
enum
|
|
{
|
|
CANCEL_SELECTION_FRAMES = 5
|
|
};
|
|
|
|
if (anyUnitSelected == true)
|
|
{
|
|
if (unselectUnits_counter < CANCEL_SELECTION_FRAMES)
|
|
{
|
|
unselectUnits_counter++;
|
|
}
|
|
else
|
|
{
|
|
if (anyUnitSelected == true)
|
|
{
|
|
uint8_t i;
|
|
|
|
// Cancel selection of all units
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
ptrUnit->selected = false;
|
|
}
|
|
}
|
|
|
|
// Reset accumulated counter and flags
|
|
unselectUnits_counter = 0;
|
|
anyUnitSelected = false;
|
|
showActionsMenu = false;
|
|
showActionsMenu_counter = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Player::ButtonBReleased(void)
|
|
{
|
|
if (anyUnitSelected == true)
|
|
{
|
|
TYPE_COLLISION_BLOCK cursor = GetCursorPos();
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
UnitMoveTo(ptrUnit, cursor.x, cursor.y);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reset accumulated counter
|
|
unselectUnits_counter = 0;
|
|
}
|
|
|
|
|
|
void Player::ButtonLeftReleased(void)
|
|
{
|
|
if (showActionsMenu == true)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
// We need to iterate over all available actions
|
|
// for current unit.
|
|
uint8_t availableActions = UnitGetAvailableActions(ptrUnit);
|
|
|
|
DEBUG_VAR(availableActions);
|
|
|
|
for (uint8_t j = showActionsMenu_index - 1; j != showActionsMenu_index ; j--)
|
|
{
|
|
if (j > (sizeof(uint8_t) << 3))
|
|
{
|
|
// Maximum index: 7
|
|
j = (sizeof(uint8_t) << 3) - 1;
|
|
}
|
|
|
|
if (availableActions & (1 << j))
|
|
{
|
|
showActionsMenu_index = j;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Player::ButtonRightReleased(void)
|
|
{
|
|
IncreaseShowActionsMenuIndex();
|
|
}
|
|
|
|
void Player::IncreaseShowActionsMenuIndex(void)
|
|
{
|
|
if (showActionsMenu == true)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < PLAYER_MAX_UNITS_BUILDINGS; i++)
|
|
{
|
|
TYPE_UNIT* ptrUnit = &units[i];
|
|
|
|
if (ptrUnit->selected == true)
|
|
{
|
|
// We need to iterate over all available actions
|
|
// for current unit.
|
|
uint8_t availableActions = UnitGetAvailableActions(ptrUnit);
|
|
|
|
DEBUG_VAR(availableActions);
|
|
|
|
for (uint8_t j = showActionsMenu_index + 1; j != showActionsMenu_index ; j++)
|
|
{
|
|
if (j >= (sizeof(uint8_t) << 3) )
|
|
{
|
|
j = 0;
|
|
}
|
|
|
|
if (availableActions & (1 << j))
|
|
{
|
|
showActionsMenu_index = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|