* Player can now select nearest unit or building. Multiple buildings and units can be selected at the same time.

* Unit module moved from C++ to C (only extension change - and compiler - was needed).
* GfxGetHeightFromSpriteData and GfxGetWidthFromSpriteData were getting incorrect data! Incorrect memory address was being read when calling pgm_read_byte, and caused unexpected behaviour under real hw.
This commit is contained in:
XaviDCR92 2017-03-12 21:09:29 +01:00
parent f416816883
commit 6628e7de58
16 changed files with 1421 additions and 1320 deletions

View File

@ -1,7 +1,7 @@
const uint8_t BarracksSpr_Data[] PROGMEM =
{
24 /* Width */ ,24 /* Height */,
0x18 /* Width */ ,0x18 /* Height */,
0xE7,0x0,0xE7,
0xBD,0x0,0xBD,
0xE7,0xFF,0xE7,

View File

@ -47,13 +47,7 @@ uint8_t BuildingGetHpFromID(uint8_t id)
void BuildingSelectedOptions(TYPE_BUILDING * ptrBuilding)
{
char str[8];
GfxDrawRectangle(0, Y_SCREEN_RESOLUTION - 8, X_SCREEN_RESOLUTION, 8, GFX_WHITE);
snprintf(str, 8, "HP=%d", ptrBuilding->hp);
GfxPrintTextFont(str, font3x3, 4, Y_SCREEN_RESOLUTION - 4);
}
@ -79,21 +73,29 @@ void BuildingDraw(TYPE_CAMERA * ptrCamera, TYPE_BUILDING * ptrBuilding, bool bSe
GfxDrawSprite(BuildingSprTable[id]);
int8_t color = GFX_WHITE;
if( (bSelected == true) && (ptrBuilding->selected == false) )
{
TYPE_COLLISION_BLOCK cb;
cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrBuilding->x, ptrBuilding->y);
GfxDrawCircle(cb.x + 3, cb.y + 3, BuildingGetWidthFromID(ptrBuilding->id) >> 2, GFX_GRAY);
color = GFX_GRAY;
}
else if(ptrBuilding->selected == true)
{
TYPE_COLLISION_BLOCK cb;
color = GFX_BLACK;
}
if(color != GFX_WHITE)
{
TYPE_COLLISION_BLOCK cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrBuilding->x, ptrBuilding->y);
cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrBuilding->x, ptrBuilding->y);
cb.w = BuildingGetWidthFromID(ptrBuilding->id);
cb.h = BuildingGetWidthFromID(ptrBuilding->id);
GfxDrawCircle(cb.x + 3, cb.y + 3, BuildingGetWidthFromID(ptrBuilding->id) >> 2, GFX_BLACK);
GfxDrawRectangle( cb.x - (cb.w / 10),
cb.y - (cb.h / 10),
BuildingGetWidthFromID(ptrBuilding->id) + (cb.w / 5),
BuildingGetHeightFromID(ptrBuilding->id) + (cb.h / 5),
color );
}
}

View File

@ -153,8 +153,41 @@ void CameraHandler(TYPE_CAMERA * ptrCamera)
CameraUpdateSpeed(ptrCamera);
}
ptrCamera->X_Offset += ptrCamera->X_Speed;
ptrCamera->Y_Offset += ptrCamera->Y_Speed;
if((ptrCamera->X_Offset + ptrCamera->X_Speed) < 0)
{
ptrCamera->X_Offset += ptrCamera->X_Speed;
if(ptrCamera->X_Offset == 0)
{
ptrCamera->X_Speed = 0;
}
}
else
{
ptrCamera->X_Offset = 0;
ptrCamera->X_Speed = 0;
}
/*char str[8];
snprintf(str, 8, "%u", ptrCamera->Y_Offset);
GfxPrintText(str, 40, 40);*/
if((ptrCamera->Y_Offset + ptrCamera->Y_Speed) < 0)
{
ptrCamera->Y_Offset += ptrCamera->Y_Speed;
if(ptrCamera->Y_Offset == 0)
{
ptrCamera->Y_Speed = 0;
}
}
else
{
ptrCamera->Y_Offset = 0;
ptrCamera->Y_Speed = 0;
}
}
bool CameraSpecialConditions(TYPE_CAMERA * ptrCamera)

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -36,10 +36,12 @@ typedef struct t_Unit
{
uint16_t x;
uint16_t y;
uint16_t target_x;
uint16_t target_y;
uint8_t hp;
uint8_t id;
bool dir; // False = up-down; true = left-right
bool walk;
bool walking;
bool alive;
bool selected;
}TYPE_UNIT;

39
Gfx.cpp
View File

@ -91,14 +91,14 @@ bool GfxIsSpriteInsideScreenArea(TYPE_SPRITE * spr)
uint8_t GfxGetWidthFromSpriteData(const uint8_t * sprData)
{
// On Gamebuino bitmaps, width is always stored on first byte.
return pgm_read_byte_near(sprData[0]) << 1;
// On Gamebuino bitmaps, width is always stored on first byte.
return pgm_read_byte_near(&sprData[0]);
}
uint8_t GfxGetHeightFromSpriteData(const uint8_t * sprData)
{
// On Gamebuino bitmaps, height is always stored on second byte.
return pgm_read_byte_near(sprData[1]) << 1;
return pgm_read_byte_near(&sprData[1]);
}
void GfxPrintText_Flash(const __FlashStringHelper * str)
@ -187,11 +187,26 @@ void GfxDrawCircle(uint16_t x, uint16_t y, uint8_t radius, int8_t color)
void GfxDrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, int8_t color)
{
int8_t orig_color = gb.display.getColor();
gb.display.setColor(color);
gb.display.fillRect(x, y, w, h);
gb.display.setColor(orig_color);
if(GfxIsInsideScreenArea(x, y, w, h) == true)
{
int8_t orig_color = gb.display.getColor();
gb.display.setColor(color);
gb.display.drawRect(x, y, w, h);
gb.display.setColor(orig_color);
}
}
void GfxFillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, int8_t color)
{
if(GfxIsInsideScreenArea(x, y, w, h) == true)
{
int8_t orig_color = gb.display.getColor();
gb.display.setColor(color);
gb.display.fillRect(x, y, w, h);
gb.display.setColor(orig_color);
}
}
void GfxShowResources(TYPE_RESOURCES * ptrResources)
@ -199,17 +214,17 @@ void GfxShowResources(TYPE_RESOURCES * ptrResources)
char str[8];
gb.display.setColor(GFX_WHITE);
gb.display.fillRect(0, 0, X_SCREEN_RESOLUTION, 8);
gb.display.fillRect(0, 0, X_SCREEN_RESOLUTION, 5);
snprintf(str, 8, "W=%d", ptrResources->Wood);
GfxPrintTextFont(str, font3x3, 4, 4);
GfxPrintTextFont(str, font3x3, 4, 1);
snprintf(str, 8, "G=%d", ptrResources->Gold);
GfxPrintTextFont(str, font3x3, 24, 4);
GfxPrintTextFont(str, font3x3, 24, 1);
snprintf(str, 8, "F=%d", ptrResources->Food);
GfxPrintTextFont(str, font3x3, 48, 4);
GfxPrintTextFont(str, font3x3, 48, 1);
}

9
Gfx.h
View File

@ -25,6 +25,14 @@ extern "C"
#define GFX_INVERT 2
#define GFX_GRAY 3
#define GFX_NOFLIP 0
#define GFX_FLIPH 1
#define GFX_FLIPV 2
#define GFX_FLIPHV 3
#define GFX_ROTCCW 1
#define GFX_ROTCW 3
/* *************************************
* Structs and enums
* *************************************/
@ -48,6 +56,7 @@ typedef struct
void GfxDrawSprite(TYPE_SPRITE * ptrSprite);
void GfxDrawCircle(uint16_t x, uint16_t y, uint8_t radius, int8_t color);
void GfxDrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, int8_t color);
void GfxFillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, int8_t color);
bool GfxRefreshNeeded(void);
void GfxShowKeyboard(char * str, uint8_t length);
uint8_t GfxGetWidthFromSpriteData(const uint8_t * sprData);

View File

@ -36,7 +36,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $< -o $@ $(INCLUDE) $(DEFINE) $(CC_FLAGS)
$(PROJECT).ELF:
$(LINKER) $(OBJ_DIR)/*.o -o Exe/$(PROJECT).elf -mmcu=$(MCU) -g $(LIBS) $(INCLUDE) -flto -Wl,--gc-sections
$(LINKER) $(OBJ_DIR)/*.o -o Exe/$(PROJECT).elf -mmcu=$(MCU) -g $(LIBS) $(INCLUDE) -flto -Xlinker -Map=Exe/POCKET.MAP -Wl,--gc-sections
$(PROJECT).HEX: $(PROJECT).ELF
avr-objcopy -j.text -j.data -j.bss -O ihex Exe/$^ $@

View File

@ -19,7 +19,12 @@ bool PadButtonReleased(PAD_BUTTONS btn)
bool PadButtonPressed(PAD_BUTTONS btn)
{
return gb.buttons.timeHeld(btn) > 0;
return PadButtonPressedFrames(btn, 0);
}
bool PadButtonPressedFrames(PAD_BUTTONS btn, uint8_t frames)
{
return gb.buttons.timeHeld(btn) > frames;
}
bool PadDirectionKeyPressed(void)

1
Pad.h
View File

@ -39,6 +39,7 @@ typedef enum t_padbuttons
bool PadButtonReleased(PAD_BUTTONS btn);
bool PadButtonPressed(PAD_BUTTONS btn);
bool PadButtonPressedFrames(PAD_BUTTONS btn, uint8_t frames);
bool PadDirectionKeyPressed(void);
bool PadAnyKeyPressed(void);

View File

@ -1,29 +1,30 @@
// Default direction: Down
const uint8_t PROGMEM Peasant_Walking_SprData[] =
{
8,8, //width and height
B01100000,
B10111100,
B11000010,
B10011001,
B10100101,
B01100111,
B00011101,
B00000010,
0x60,
0xBC,
0xC2,
0x99,
0xA5,
0x67,
0x1D,
0x02,
};
const uint8_t PROGMEM Peasant_SprData[] =
{
8,8, //width and height
B00000000,
B00111100,
B01000010,
B10011001,
B10100101,
B01100110,
B00011000,
B00000000,
0x00,
0x3C,
0x42,
0x99,
0xA5,
0x66,
0x18,
0x00,
};

View File

@ -8,6 +8,8 @@
* Defines *
* **************************************/
#define CANCEL_SELECTION_NO_FRAMES 5
/* **************************************
* Local variables *
* **************************************/
@ -72,6 +74,17 @@ void Player::Init(void)
}
}
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;
@ -82,12 +95,20 @@ void Player::DrawHandler(void)
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);
}
}
@ -95,12 +116,20 @@ void Player::DrawHandler(void)
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);
}
}
@ -234,6 +263,12 @@ void Player::UnitBuildingSelection(void)
for(i = 0; i < PLAYER_MAX_UNITS; i++)
{
TYPE_UNIT * u = &units[i];
if(u->alive == false)
{
continue;
}
TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos();
TYPE_COLLISION_BLOCK u_cb = {u->x, u->y, UnitGetWidthFromID(u->id), UnitGetHeightFromID(u->id) };
@ -255,6 +290,12 @@ void Player::UnitBuildingSelection(void)
for(i = 0; i < PLAYER_MAX_BUILDINGS; i++)
{
TYPE_BUILDING * b = &buildings[i];
if(b->built == false)
{
continue;
}
TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos();
TYPE_COLLISION_BLOCK u_cb = {b->x, b->y, BuildingGetWidthFromID(b->id), BuildingGetHeightFromID(b->id) };
@ -281,7 +322,15 @@ void Player::UnitBuildingSelection(void)
selectedBuilding = NULL;
}
char buf[8];
if( (nearest_unit_dist > 400)
&&
(nearest_building_dist > 400) )
{
selectedUnit = NULL;
selectedBuilding = NULL;
}
/*char buf[8];
snprintf(buf, 8, "%lu", nearest_building_dist);
@ -289,15 +338,24 @@ void Player::UnitBuildingSelection(void)
snprintf(buf, 8, "%lu", nearest_unit_dist);
GfxPrintText(buf, X_SCREEN_RESOLUTION - 32, 24);
GfxPrintText(buf, X_SCREEN_RESOLUTION - 32, 24);*/
}
void Player::Handler(void)
{
{
static bool bCancelSelection = false;
CameraHandler(&Camera);
UnitBuildingSelection();
for(int i = 0; i < PLAYER_MAX_UNITS; i++)
{
TYPE_UNIT * ptrUnit = &units[i];
UnitHandler(ptrUnit);
}
if(PadButtonReleased(PAD_A) == true)
{
/*TYPE_COLLISION_BLOCK cl;
@ -336,6 +394,52 @@ void Player::Handler(void)
}
}
}
else if( (PadButtonPressedFrames(PAD_B, CANCEL_SELECTION_NO_FRAMES) == true)
&&
(bCancelSelection == false) )
{
for(int i = 0; i < PLAYER_MAX_UNITS; i++)
{
TYPE_UNIT * u = &units[i];
u->selected = false;
}
for(int i = 0; i < PLAYER_MAX_BUILDINGS; i++)
{
TYPE_BUILDING * b = &buildings[i];
b->selected = false;
}
selectedUnit = NULL;
selectedBuilding = NULL;
bCancelSelection = true;
}
if( (PadButtonReleased(PAD_B) == true)
&&
(bCancelSelection == false) )
{
TYPE_COLLISION_BLOCK cursor = GetCursorPos();
for(int i = 0; i < PLAYER_MAX_UNITS; i++)
{
TYPE_UNIT * u = &units[i];
if(u->selected == true)
{
UnitMoveTo(u, cursor.x, cursor.y);
}
}
}
else if( (PadButtonReleased(PAD_B) == true)
&&
(bCancelSelection == true) )
{
bCancelSelection = false;
}
GfxShowResources(&Resources);
}

View File

@ -46,6 +46,7 @@ class Player
private:
bool checkNewBuildingPosition(TYPE_COLLISION_BLOCK * cb);
void UnitBuildingSelection(void);
void showHealth(uint8_t hp);
TYPE_COLLISION_BLOCK GetCursorPos(void);
char name[PLAYER_NAME_LENGTH];
TYPE_UNIT units[PLAYER_MAX_UNITS];

Binary file not shown.

108
Unit.cpp
View File

@ -1,108 +0,0 @@
/* **************************************
* Includes *
* **************************************/
#include "Unit.h"
#include "PeasantSpr.c"
/* **************************************
* Defines *
* **************************************/
/* **************************************
* Local variables *
* **************************************/
/* Sprites */
static TYPE_SPRITE PeasantSpr;
static TYPE_SPRITE PeasantWalkingSpr;
/* Tables */
static uint8_t UnitHPTable[] = { 25 };
static TYPE_SPRITE * UnitSprTable[] = {&PeasantSpr};
static TYPE_SPRITE * UnitWalkingSprTable[] = {&PeasantWalkingSpr};
void UnitInit(void)
{
PeasantSpr.Data = Peasant_SprData;
PeasantSpr.w = GfxGetWidthFromSpriteData(Peasant_SprData);
PeasantSpr.h = GfxGetHeightFromSpriteData(Peasant_SprData);
PeasantSpr.flip = 0;
PeasantSpr.rotation = 0;
PeasantSpr.color = GFX_BLACK;
PeasantWalkingSpr.Data = Peasant_Walking_SprData;
PeasantWalkingSpr.w = GfxGetWidthFromSpriteData(Peasant_Walking_SprData);
PeasantWalkingSpr.h = GfxGetHeightFromSpriteData(Peasant_Walking_SprData);
PeasantWalkingSpr.flip = 0;
PeasantWalkingSpr.rotation = 0;
PeasantWalkingSpr.color = GFX_BLACK;
}
void UnitDraw(TYPE_CAMERA * ptrCamera, TYPE_UNIT * ptrUnit, bool bSelected)
{
uint8_t id = ptrUnit->id;
TYPE_SPRITE * ptrSpr;
static uint8_t walk_counter = 0;
static bool mirror = false;
if(ptrUnit->alive == false)
{
return;
}
ptrSpr = ptrUnit->walk ? UnitWalkingSprTable[id] : UnitSprTable[id];
ptrSpr->rotation = ptrUnit->dir ? ROTCCW : NOROT;
ptrSpr->flip = mirror ? FLIPH : NOFLIP;
CameraApplyCoordinatesToSprite( ptrCamera,
ptrSpr,
ptrUnit->x,
ptrUnit->y );
GfxDrawSprite(ptrSpr);
if( (bSelected == true) && (ptrUnit->selected == false) )
{
TYPE_COLLISION_BLOCK cb;
cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrUnit->x, ptrUnit->y);
GfxDrawCircle(cb.x + 3, cb.y + 3, UnitGetWidthFromID(ptrUnit->id) >> 2, GFX_GRAY);
}
else if(ptrUnit->selected == true)
{
TYPE_COLLISION_BLOCK cb;
cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrUnit->x, ptrUnit->y);
GfxDrawCircle(cb.x + 3, cb.y + 3, UnitGetWidthFromID(ptrUnit->id) >> 2, GFX_BLACK);
}
if(++walk_counter > 10)
{
walk_counter = 0;
mirror = mirror ? true : false;
}
}
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 UnitSelectedOptions(TYPE_UNIT* ptrUnit)
{
}