/* ************************************** * Includes * * **************************************/ #include "Player.h" /* ************************************** * Defines * * **************************************/ #define CANCEL_SELECTION_NO_FRAMES 5 #define ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES 5 #define MAX_SELECTION_DIST 400 /* ************************************** * Local variables * * **************************************/ Player::Player(void) { } Player::~Player(void) { } void Player::Init(void) { uint8_t i; unit_i = 0; bldg_i = 0; selectedUnit = NULL; selectedBuilding = NULL; CameraInit(&Camera); BuildingInit(); UnitInit(); for(i = 0; i < PLAYER_MAX_BUILDINGS; i++) { memset(&buildings[i], 0, sizeof(TYPE_BUILDING)); } for(i = 0; i < PLAYER_MAX_UNITS; i++) { memset(&units[i], 0, sizeof(TYPE_UNIT)); } TYPE_COLLISION_BLOCK cl; Resources.Wood = 25; Resources.Gold = 50; Resources.Food = 75; cl.x = SystemRand(0, 20); cl.y = SystemRand(0, 20); cl.w = BuildingGetWidthFromID(BARRACKS); cl.h = BuildingGetHeightFromID(BARRACKS); if(createBuilding(BARRACKS, cl) == false) { GfxPrintText_Flash(F("Failed to create building!")); } cl.x = SystemRand(48, 56); cl.y = SystemRand(48, 56); cl.w = UnitGetWidthFromID(PEASANT); cl.h = UnitGetHeightFromID(PEASANT); if(createUnit(PEASANT, cl) == false) { GfxPrintText_Flash(F("Failed to create unit!")); } } void Player::showHealth(uint8_t hp) { char str[8]; GfxFillRectangle(0, Y_SCREEN_RESOLUTION - 5, X_SCREEN_RESOLUTION, 8, GFX_WHITE); snprintf(str, 8, "HP=%u", hp); GfxPrintTextFont(str, font3x3, 4, Y_SCREEN_RESOLUTION - 4); } void Player::DrawHandler(void) { uint8_t i; bool bAnyoneSelected = false; //GfxRenderTiles(&Camera); for(i = 0; i < PLAYER_MAX_BUILDINGS; i++) { TYPE_BUILDING * b = &buildings[i]; if(b->built == false) { continue; } bool selected = (b == selectedBuilding); BuildingDraw(&Camera, b, selected); if( (b->selected == true) && (bAnyoneSelected == false) ) { bAnyoneSelected = true; showHealth(b->hp); BuildingSelectedOptions(b); } } for(i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT * u = &units[i]; if(u->alive == false) { continue; } bool selected = (u == selectedUnit); UnitDraw(&Camera, u, selected); if( (u->selected == true) && (bAnyoneSelected == false) ) { bAnyoneSelected = true; showHealth(u->hp); UnitSelectedOptions(u); } } if(progress_bar != 0) { GfxDrawRectangle(X_SCREEN_RESOLUTION - 16, Y_SCREEN_RESOLUTION - 4, progress_bar, 2, 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_BUILDINGS; i++) { success = false; if(buildings[i].built == false) { continue; } bldgCB.x = buildings[i].x; bldgCB.y = buildings[i].y; bldgCB.w = BuildingGetWidthFromID(buildings[i].id); bldgCB.h = BuildingGetHeightFromID(buildings[i].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::createBuilding(uint8_t id, TYPE_COLLISION_BLOCK cb) { if(checkNewBuildingPosition(&cb) == false) { return false; } if(bldg_i < PLAYER_MAX_BUILDINGS) { buildings[bldg_i].id = id; buildings[bldg_i].x = cb.x; buildings[bldg_i].y = cb.y; buildings[bldg_i].hp = BuildingGetHpFromID(id); buildings[bldg_i].built = true; bldg_i++; return true; } else { return false; } return false; } bool Player::createUnit(uint8_t id, TYPE_COLLISION_BLOCK cb) { if(unit_i < PLAYER_MAX_UNITS) { units[unit_i].id = id; units[unit_i].x = cb.x; units[unit_i].y = cb.y; units[unit_i].hp = UnitGetHpFromID(id); units[unit_i].alive = true; 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; TYPE_UNIT * nearest_unit = NULL; uint32_t nearest_unit_dist = 0xFFFFFFFF; // Set maximum value uint32_t dist; for(i = 0; i < PLAYER_MAX_UNITS; 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 - cursor_cb.x); uint16_t dist_y = (u_cb.y - cursor_cb.y); dist = (dist_x * dist_x) + (dist_y * dist_y); if(dist < nearest_unit_dist) { nearest_unit_dist = dist; nearest_unit = u; } } TYPE_BUILDING * nearest_building = NULL; uint32_t nearest_building_dist = 0xFFFFFFFF; // Set maximum value for(i = 0; i < PLAYER_MAX_BUILDINGS; i++) { TYPE_BUILDING * b = &buildings[i]; if( (b->built == false) || (b->selected == true) ) { continue; } TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos(); TYPE_COLLISION_BLOCK u_cb = {b->x, b->y, BuildingGetWidthFromID(b->id), BuildingGetHeightFromID(b->id) }; uint16_t dist_x = (u_cb.x + (u_cb.w >> 1) - cursor_cb.x + 4); uint16_t dist_y = (u_cb.y + (u_cb.h >> 1) - cursor_cb.y + 4); dist = (dist_x * dist_x) + (dist_y * dist_y); if(dist < nearest_building_dist) { nearest_building_dist = dist; nearest_building = b; } } if(nearest_building_dist <= nearest_unit_dist) { selectedUnit = NULL; selectedBuilding = nearest_building; } else { selectedUnit = nearest_unit; selectedBuilding = NULL; } if( (nearest_unit_dist > MAX_SELECTION_DIST) && (nearest_building_dist > MAX_SELECTION_DIST) ) { selectedUnit = NULL; selectedBuilding = NULL; } /*char buf[8]; snprintf(buf, 8, "%lu", nearest_building_dist); GfxPrintText(buf, X_SCREEN_RESOLUTION - 32, 16); snprintf(buf, 8, "%lu", nearest_unit_dist); GfxPrintText(buf, X_SCREEN_RESOLUTION - 32, 24);*/ } void Player::BuildingUnitActions(void) { const char* pActionStr = NULL; for(uint8_t i = 0; i < PLAYER_MAX_BUILDINGS; i++) { if(buildings[i].selected == true) { BuildingSelectedOptions(selectedBuilding); break; } } if(pActionStr == NULL) { for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { if(units[i].selected == true) { pActionStr = UnitSelectedOptions(selectedUnit); break; } } } if(pActionStr != NULL) { GfxPrintTextFont(pActionStr, font3x3, 48, Y_SCREEN_RESOLUTION - 4); } } void Player::Handler(void) { CameraHandler(&Camera); UnitBuildingSelection(); for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT * ptrUnit = &units[i]; UnitHandler(ptrUnit); } ButtonHandler(); BuildingUnitActions(); GfxShowResources(&Resources); } void Player::ButtonHandler(void) { static bool bCancelSelection = false; if(PadButtonPressed(PAD_A) == true) { if(progress_bar < ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES) { progress_bar++; } } if(PadButtonReleased(PAD_A) == true) { /*TYPE_COLLISION_BLOCK cl; cl.x = SystemRand(0, 32); cl.y = SystemRand(0, 32); cl.w = BuildingGetWidthFromID(BARRACKS); cl.h = BuildingGetHeightFromID(BARRACKS); if(createBuilding(BARRACKS, cl) == false) { GfxPrintText_Flash(F("Failed!")); } else { GfxPrintText_Flash(F("Building built!\0")); }*/ for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT * u = &units[i]; if(selectedUnit == u) { u->selected = true; } } for(uint8_t i = 0; i < PLAYER_MAX_BUILDINGS; i++) { TYPE_BUILDING * b = &buildings[i]; if(selectedBuilding == b) { b->selected = true; } } } else if(PadButtonPressedFrames(PAD_A, ACCEPT_UNIT_BUILDING_OPTIONS_FRAMES) == true) { for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT* u = &units[i]; if(u->selected == true) { UnitAcceptAction(u); break; } } } else if( (PadButtonPressedFrames(PAD_B, CANCEL_SELECTION_NO_FRAMES) == true) && (bCancelSelection == false) ) { for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT * u = &units[i]; u->selected = false; } for(uint8_t i = 0; i < PLAYER_MAX_BUILDINGS; i++) { TYPE_BUILDING * b = &buildings[i]; b->selected = false; } selectedUnit = NULL; selectedBuilding = NULL; bCancelSelection = true; showUnitBuildingOptions = true; } else { // Button A is not pressed. Reset progress bar. progress_bar = 0; } if( (PadButtonReleased(PAD_B) == true) && (bCancelSelection == false) ) { if(showUnitBuildingOptions == false) { TYPE_COLLISION_BLOCK cursor = GetCursorPos(); for(uint8_t i = 0; i < PLAYER_MAX_UNITS; i++) { TYPE_UNIT * u = &units[i]; if(u->selected == true) { UnitMoveTo(u, cursor.x, cursor.y); } } } else { showUnitBuildingOptions = false; } } else if( (PadButtonReleased(PAD_B) == true) && (bCancelSelection == true) ) { bCancelSelection = false; UnitResetMenuLevel(); } }