PocketEmpires/Unit.c

293 lines
8.3 KiB
C

/* **************************************
* Includes *
* **************************************/
#include "Unit.h"
#include "PeasantSpr.c"
#include "BarracksSpr.c"
/* **************************************
* Defines *
* **************************************/
#define MAX_ACTIONS 3
/* **************************************
* Structs and enums *
* **************************************/
struct t_coordinates
{
int8_t x;
int8_t y;
};
/* **************************************
* Local prototypes *
* **************************************/
static void UnitBuildAccepted(TYPE_UNIT* ptrUnit);
static void UnitAttackAccepted(TYPE_UNIT* ptrUnit);
/* **************************************
* Local variables *
* **************************************/
/* Tables */
static uint8_t const UnitHPTable[MAX_UNITS_BUILDINGS] = { [PEASANT] = 25 ,
[BARRACKS] = 100 };
static uint8_t const UnitSpeedTable[MAX_UNITS_BUILDINGS] = { [PEASANT] = 1 ,
[BARRACKS] = 0 };
static TYPE_UNIT_ACTION const UnitActionsTable_Level0[MAX_ACTIONS] = { [ACTION_BUILD] = {"BUILD", &UnitBuildAccepted} ,
[ACTION_ATTACK] = {"ATTACK", &UnitAttackAccepted} ,
[ACTION_CREATE_UNIT] = {"CREATE", NULL} };
static uint8_t const UnitActionsTable[MAX_UNITS_BUILDINGS] = { [PEASANT] = ((1 << ACTION_BUILD) | (1 << ACTION_ATTACK)),
[BARRACKS] = (1 << ACTION_CREATE_UNIT) };
// **************
// Sprite tables
// **************
static TYPE_SPRITE UnitSprTable[MAX_UNITS_BUILDINGS];
static TYPE_SPRITE UnitWalkingShadowSprTable[MAX_UNITS_BUILDINGS];
static const struct t_coordinates UnitShadowOffsetTable[MAX_BUILDING_ID - FIRST_BUILDING_ID] = { [BARRACKS - FIRST_BUILDING_ID] = {.x = -6, .y = 0} };
void UnitInit(void)
{
enum
{
BARRACKS_SHADOW_OFFSET_X = -8,
BARRACKS_SHADOW_OFFSET_Y = 0
};
UnitSprTable[PEASANT].Data = Peasant_SprData;
UnitSprTable[PEASANT].w = GfxGetWidthFromSpriteData(Peasant_SprData);
UnitSprTable[PEASANT].h = GfxGetHeightFromSpriteData(Peasant_SprData);
UnitSprTable[PEASANT].flip = 0;
UnitSprTable[PEASANT].rotation = 0;
UnitSprTable[PEASANT].color = GFX_BLACK;
UnitWalkingShadowSprTable[PEASANT].Data = Peasant_Walking_SprData;
UnitWalkingShadowSprTable[PEASANT].w = GfxGetWidthFromSpriteData(Peasant_Walking_SprData);
UnitWalkingShadowSprTable[PEASANT].h = GfxGetHeightFromSpriteData(Peasant_Walking_SprData);
UnitWalkingShadowSprTable[PEASANT].flip = 0;
UnitWalkingShadowSprTable[PEASANT].rotation = 0;
UnitWalkingShadowSprTable[PEASANT].color = GFX_BLACK;
UnitSprTable[BARRACKS].Data = BarracksSpr_Data;
UnitSprTable[BARRACKS].w = GfxGetWidthFromSpriteData(BarracksSpr_Data);
UnitSprTable[BARRACKS].h = GfxGetHeightFromSpriteData(BarracksSpr_Data);
UnitSprTable[BARRACKS].flip = 0;
UnitSprTable[BARRACKS].rotation = 0;
UnitSprTable[BARRACKS].color = GFX_BLACK;
UnitWalkingShadowSprTable[BARRACKS].Data = BarracksShadowSpr_Data;
UnitWalkingShadowSprTable[BARRACKS].w = GfxGetWidthFromSpriteData(BarracksShadowSpr_Data);
UnitWalkingShadowSprTable[BARRACKS].h = GfxGetHeightFromSpriteData(BarracksShadowSpr_Data);
UnitWalkingShadowSprTable[BARRACKS].flip = 0;
UnitWalkingShadowSprTable[BARRACKS].rotation = 0;
UnitWalkingShadowSprTable[BARRACKS].color = GFX_GRAY;
}
void UnitDraw(TYPE_UNIT* ptrUnit, TYPE_CAMERA* ptrCamera, bool bHighlighted)
{
uint8_t id = ptrUnit->id;
TYPE_SPRITE * ptrSpr;
if (ptrUnit->alive == false)
{
return;
}
if (ptrUnit->building == false)
{
enum
{
WALK_FRAMES = 4
};
// ***************
// Units
// ***************
ptrSpr = ptrUnit->walking ? &UnitWalkingShadowSprTable[id] : &UnitSprTable[id];
ptrSpr->rotation = GFX_NOROT;
ptrSpr->flip = GFX_NOFLIP;
if (ptrUnit->walking == true)
{
if (++ptrUnit->walk_counter > WALK_FRAMES)
{
ptrUnit->walk_counter = 0;
ptrUnit->mirror = ptrUnit->mirror ? false : true;
}
}
switch (ptrUnit->dir)
{
case DIRECTION_UP:
ptrSpr->flip |= GFX_FLIPV;
if (ptrUnit->mirror == true)
{
ptrSpr->flip |= GFX_FLIPH;
}
break;
case DIRECTION_DOWN:
if (ptrUnit->mirror == true)
{
ptrSpr->flip |= GFX_FLIPH;
}
break;
case DIRECTION_LEFT:
ptrSpr->rotation = GFX_ROTCCW;
ptrSpr->flip |= GFX_FLIPH;
if (ptrUnit->mirror == true)
{
ptrSpr->flip |= GFX_FLIPV;
}
break;
case DIRECTION_RIGHT:
ptrSpr->rotation = GFX_ROTCCW;
if (ptrUnit->mirror == true)
{
ptrSpr->flip |= GFX_FLIPV;
}
break;
default:
// Invalid direction
break;
}
}
else
{
// *******************
// Buildings
// *******************
CameraApplyCoordinatesToSprite( ptrCamera,
&UnitWalkingShadowSprTable[id],
ptrUnit->x + UnitShadowOffsetTable[id - FIRST_BUILDING_ID].x,
ptrUnit->y + UnitShadowOffsetTable[id - FIRST_BUILDING_ID].y );
GfxDrawSprite(&UnitWalkingShadowSprTable[id]);
ptrSpr = &UnitSprTable[id];
}
CameraApplyCoordinatesToSprite( ptrCamera,
ptrSpr,
ptrUnit->x,
ptrUnit->y );
GfxDrawSprite(ptrSpr);
if ( (bHighlighted == true) || (ptrUnit->selected == true) )
{
TYPE_COLLISION_BLOCK cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrUnit->x, ptrUnit->y);
int8_t colour = ptrUnit->selected? GFX_BLACK : GFX_GRAY;
uint8_t w = UnitGetWidthFromID(id);
uint8_t h = UnitGetHeightFromID(id);
if (ptrUnit->building == true)
{
GfxDrawRectangle(cb.x - (w >> 3), cb.y - (h >> 3), w + (w >> 2), h + (h >> 2), colour);
}
else
{
GfxDrawCircle(cb.x + (w >> 1), cb.y + (h >> 1), w, colour);
}
}
}
uint8_t UnitGetWidthFromID(uint8_t id)
{
return GfxGetWidthFromSpriteData(UnitSprTable[id].Data);
}
uint8_t UnitGetHeightFromID(uint8_t id)
{
return GfxGetHeightFromSpriteData(UnitSprTable[id].Data);
}
uint8_t UnitGetHpFromID(uint8_t id)
{
return UnitHPTable[id];
}
void UnitMoveTo(TYPE_UNIT* ptrUnit, uint16_t x, uint16_t y)
{
ptrUnit->target_x = x;
ptrUnit->target_y = y;
ptrUnit->walking = true;
}
void UnitAttackAccepted(TYPE_UNIT* ptrUnit)
{
ptrUnit->selecting_attack = true;
}
void UnitHandler(TYPE_UNIT* ptrUnit)
{
bool bMoving = false;
if (ptrUnit->walking == true)
{
if ( (ptrUnit->x - UnitSpeedTable[ptrUnit->id]) > ptrUnit->target_x)
{
ptrUnit->dir = DIRECTION_LEFT;
ptrUnit->x -= UnitSpeedTable[ptrUnit->id];
bMoving = true;
}
else if ( (ptrUnit->x + UnitSpeedTable[ptrUnit->id]) < ptrUnit->target_x)
{
ptrUnit->dir = DIRECTION_RIGHT;
ptrUnit->x += UnitSpeedTable[ptrUnit->id];
bMoving = true;
}
if ( (ptrUnit->y - UnitSpeedTable[ptrUnit->id]) > ptrUnit->target_y)
{
ptrUnit->dir = DIRECTION_UP;
ptrUnit->y -= UnitSpeedTable[ptrUnit->id];
bMoving = true;
}
else if ( (ptrUnit->y + UnitSpeedTable[ptrUnit->id]) < ptrUnit->target_y)
{
ptrUnit->dir = DIRECTION_DOWN;
ptrUnit->y += UnitSpeedTable[ptrUnit->id];
bMoving = true;
}
ptrUnit->walking = bMoving;
}
}
void UnitAcceptAction(TYPE_UNIT* ptrUnit)
{
}
uint8_t UnitGetAvailableActions(TYPE_UNIT* ptrUnit)
{
return UnitActionsTable[ptrUnit->id];
}
void UnitBuildAccepted(TYPE_UNIT* ptrUnit)
{
}
const char* UnitGetActionString(UNIT_ACTION action)
{
return UnitActionsTable_Level0[action].str;
}