* 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 = const uint8_t BarracksSpr_Data[] PROGMEM =
{ {
24 /* Width */ ,24 /* Height */, 0x18 /* Width */ ,0x18 /* Height */,
0xE7,0x0,0xE7, 0xE7,0x0,0xE7,
0xBD,0x0,0xBD, 0xBD,0x0,0xBD,
0xE7,0xFF,0xE7, 0xE7,0xFF,0xE7,

View File

@ -47,13 +47,7 @@ uint8_t BuildingGetHpFromID(uint8_t id)
void BuildingSelectedOptions(TYPE_BUILDING * ptrBuilding) 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]); GfxDrawSprite(BuildingSprTable[id]);
int8_t color = GFX_WHITE;
if( (bSelected == true) && (ptrBuilding->selected == false) ) if( (bSelected == true) && (ptrBuilding->selected == false) )
{ {
TYPE_COLLISION_BLOCK cb; color = GFX_GRAY;
cb = CameraApplyCoordinatesToCoordinates(ptrCamera, ptrBuilding->x, ptrBuilding->y);
GfxDrawCircle(cb.x + 3, cb.y + 3, BuildingGetWidthFromID(ptrBuilding->id) >> 2, GFX_GRAY);
} }
else if(ptrBuilding->selected == true) 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); CameraUpdateSpeed(ptrCamera);
} }
ptrCamera->X_Offset += ptrCamera->X_Speed; if((ptrCamera->X_Offset + ptrCamera->X_Speed) < 0)
ptrCamera->Y_Offset += ptrCamera->Y_Speed; {
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) 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 x;
uint16_t y; uint16_t y;
uint16_t target_x;
uint16_t target_y;
uint8_t hp; uint8_t hp;
uint8_t id; uint8_t id;
bool dir; // False = up-down; true = left-right bool dir; // False = up-down; true = left-right
bool walk; bool walking;
bool alive; bool alive;
bool selected; bool selected;
}TYPE_UNIT; }TYPE_UNIT;

39
Gfx.cpp
View File

@ -91,14 +91,14 @@ bool GfxIsSpriteInsideScreenArea(TYPE_SPRITE * spr)
uint8_t GfxGetWidthFromSpriteData(const uint8_t * sprData) uint8_t GfxGetWidthFromSpriteData(const uint8_t * sprData)
{ {
// On Gamebuino bitmaps, width is always stored on first byte. // On Gamebuino bitmaps, width is always stored on first byte.
return pgm_read_byte_near(sprData[0]) << 1; return pgm_read_byte_near(&sprData[0]);
} }
uint8_t GfxGetHeightFromSpriteData(const uint8_t * sprData) uint8_t GfxGetHeightFromSpriteData(const uint8_t * sprData)
{ {
// On Gamebuino bitmaps, height is always stored on second byte. // 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) 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) void GfxDrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, int8_t color)
{ {
int8_t orig_color = gb.display.getColor(); if(GfxIsInsideScreenArea(x, y, w, h) == true)
{
gb.display.setColor(color); int8_t orig_color = gb.display.getColor();
gb.display.fillRect(x, y, w, h);
gb.display.setColor(orig_color); 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) void GfxShowResources(TYPE_RESOURCES * ptrResources)
@ -199,17 +214,17 @@ void GfxShowResources(TYPE_RESOURCES * ptrResources)
char str[8]; char str[8];
gb.display.setColor(GFX_WHITE); 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); snprintf(str, 8, "W=%d", ptrResources->Wood);
GfxPrintTextFont(str, font3x3, 4, 4); GfxPrintTextFont(str, font3x3, 4, 1);
snprintf(str, 8, "G=%d", ptrResources->Gold); snprintf(str, 8, "G=%d", ptrResources->Gold);
GfxPrintTextFont(str, font3x3, 24, 4); GfxPrintTextFont(str, font3x3, 24, 1);
snprintf(str, 8, "F=%d", ptrResources->Food); 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_INVERT 2
#define GFX_GRAY 3 #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 * Structs and enums
* *************************************/ * *************************************/
@ -48,6 +56,7 @@ typedef struct
void GfxDrawSprite(TYPE_SPRITE * ptrSprite); void GfxDrawSprite(TYPE_SPRITE * ptrSprite);
void GfxDrawCircle(uint16_t x, uint16_t y, uint8_t radius, int8_t color); 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 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); bool GfxRefreshNeeded(void);
void GfxShowKeyboard(char * str, uint8_t length); void GfxShowKeyboard(char * str, uint8_t length);
uint8_t GfxGetWidthFromSpriteData(const uint8_t * sprData); 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) $(CC) $< -o $@ $(INCLUDE) $(DEFINE) $(CC_FLAGS)
$(PROJECT).ELF: $(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 $(PROJECT).HEX: $(PROJECT).ELF
avr-objcopy -j.text -j.data -j.bss -O ihex Exe/$^ $@ 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) 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) bool PadDirectionKeyPressed(void)

1
Pad.h
View File

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

View File

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

View File

@ -8,6 +8,8 @@
* Defines * * Defines *
* **************************************/ * **************************************/
#define CANCEL_SELECTION_NO_FRAMES 5
/* ************************************** /* **************************************
* Local variables * * 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) void Player::DrawHandler(void)
{ {
uint8_t i; uint8_t i;
@ -82,12 +95,20 @@ void Player::DrawHandler(void)
for(i = 0; i < PLAYER_MAX_BUILDINGS; i++) for(i = 0; i < PLAYER_MAX_BUILDINGS; i++)
{ {
TYPE_BUILDING * b = &buildings[i]; TYPE_BUILDING * b = &buildings[i];
if(b->built == false)
{
continue;
}
bool selected = (b == selectedBuilding); bool selected = (b == selectedBuilding);
BuildingDraw(&Camera, b, selected); BuildingDraw(&Camera, b, selected);
if( (b->selected == true) && (bAnyoneSelected == false) ) if( (b->selected == true) && (bAnyoneSelected == false) )
{ {
bAnyoneSelected = true; bAnyoneSelected = true;
showHealth(b->hp);
BuildingSelectedOptions(b); BuildingSelectedOptions(b);
} }
} }
@ -95,12 +116,20 @@ void Player::DrawHandler(void)
for(i = 0; i < PLAYER_MAX_UNITS; i++) for(i = 0; i < PLAYER_MAX_UNITS; i++)
{ {
TYPE_UNIT * u = &units[i]; TYPE_UNIT * u = &units[i];
if(u->alive == false)
{
continue;
}
bool selected = (u == selectedUnit); bool selected = (u == selectedUnit);
UnitDraw(&Camera, u, selected); UnitDraw(&Camera, u, selected);
if( (u->selected == true) && (bAnyoneSelected == false) ) if( (u->selected == true) && (bAnyoneSelected == false) )
{ {
bAnyoneSelected = true; bAnyoneSelected = true;
showHealth(u->hp);
UnitSelectedOptions(u); UnitSelectedOptions(u);
} }
} }
@ -234,6 +263,12 @@ void Player::UnitBuildingSelection(void)
for(i = 0; i < PLAYER_MAX_UNITS; i++) for(i = 0; i < PLAYER_MAX_UNITS; i++)
{ {
TYPE_UNIT * u = &units[i]; TYPE_UNIT * u = &units[i];
if(u->alive == false)
{
continue;
}
TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos(); TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos();
TYPE_COLLISION_BLOCK u_cb = {u->x, u->y, UnitGetWidthFromID(u->id), UnitGetHeightFromID(u->id) }; 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++) for(i = 0; i < PLAYER_MAX_BUILDINGS; i++)
{ {
TYPE_BUILDING * b = &buildings[i]; TYPE_BUILDING * b = &buildings[i];
if(b->built == false)
{
continue;
}
TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos(); TYPE_COLLISION_BLOCK cursor_cb = GetCursorPos();
TYPE_COLLISION_BLOCK u_cb = {b->x, b->y, BuildingGetWidthFromID(b->id), BuildingGetHeightFromID(b->id) }; 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; 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); snprintf(buf, 8, "%lu", nearest_building_dist);
@ -289,15 +338,24 @@ void Player::UnitBuildingSelection(void)
snprintf(buf, 8, "%lu", nearest_unit_dist); 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) void Player::Handler(void)
{ {
static bool bCancelSelection = false;
CameraHandler(&Camera); CameraHandler(&Camera);
UnitBuildingSelection(); UnitBuildingSelection();
for(int i = 0; i < PLAYER_MAX_UNITS; i++)
{
TYPE_UNIT * ptrUnit = &units[i];
UnitHandler(ptrUnit);
}
if(PadButtonReleased(PAD_A) == true) if(PadButtonReleased(PAD_A) == true)
{ {
/*TYPE_COLLISION_BLOCK cl; /*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); GfxShowResources(&Resources);
} }

View File

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