/* ************************************** * 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; }