From 374f31c9d21965938f0ce5421e1789a5226b111b Mon Sep 17 00:00:00 2001 From: commandblockguy Date: Tue, 4 Aug 2020 18:37:34 -0500 Subject: [PATCH] Add kill counter and mission/life counter banner --- src/graphics.c | 6 ++++ src/gui.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gui.h | 4 +++ src/mine.c | 2 +- src/shell.c | 2 +- 5 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/graphics.c b/src/graphics.c index b10dde0..0e0b81c 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -21,6 +21,7 @@ #include "profiler.h" #include "partial_redraw.h" #include "dynamic_sprites.h" +#include "gui.h" uint8_t tilemap[TILEMAP_HEIGHT][TILEMAP_WIDTH]; // For each tilemap tile, the level Y of the block that it's representing @@ -282,6 +283,8 @@ void redraw_tile(uint8_t x, uint8_t y) { void full_redraw(void) { gfx_FillScreen(COL_WHITE); gfx_Tilemap(&tilemap_config, 0, 0); + displayGameBanner(game.mission + 1, game.lives); + displayGameKillCounter(); } // Convert a screenspace coordinate to a redraw tile @@ -382,10 +385,13 @@ void render(level_t *level) { gfx_SetDrawBuffer(); full_redraw(); pdraw_FreeAll(); + updateGameKillCounter(game.total_kills, true); needs_redraw = false; profiler_end(tilemap); } + updateGameKillCounter(game.total_kills, false); + profiler_start(undraw); pdraw_RemoveSprites(); profiler_end(undraw); diff --git a/src/gui.c b/src/gui.c index 09d6e58..a118760 100644 --- a/src/gui.c +++ b/src/gui.c @@ -2,6 +2,8 @@ #include #include #include +#undef NDEBUG +#include #include "gui.h" @@ -177,3 +179,82 @@ void missionStartScreen(uint8_t mission, uint8_t lives, uint8_t num_tanks) { gfx_BlitBuffer(); } + +#define KILL_COUNTER_END_X (SCREEN_DELTA_X(2.75 * TILE_SIZE)) +#define KILL_COUNTER_INNER_END_X (SCREEN_DELTA_X(2.4 * TILE_SIZE)) +#define KILL_COUNTER_HEIGHT (SCREEN_DELTA_Y(2 * TILE_SIZE)) +#define KILL_COUNTER_INNER_HEIGHT (SCREEN_DELTA_Y(1.5 * TILE_SIZE)) +#define KILL_COUNTER_RADIUS (KILL_COUNTER_HEIGHT / 2) +#define KILL_COUNTER_INNER_RADIUS (KILL_COUNTER_INNER_HEIGHT / 2) +#define KILL_COUNTER_Y (SCREEN_Y(LEVEL_SIZE_Y * TILE_SIZE - TILE_SIZE)) +#define KILL_COUNTER_INNER_Y (KILL_COUNTER_Y + KILL_COUNTER_RADIUS - KILL_COUNTER_INNER_RADIUS + 1) + +void updateKillCounterCurrBuf(uint8_t kills) { + uint8_t digits = 1 + (kills > 9 ) + (kills > 99); + uint8_t width = gfx_GetCharWidth('1') * digits; + uint8_t x = KILL_COUNTER_INNER_END_X - KILL_COUNTER_INNER_RADIUS - width; + gfx_SetColor(COL_WHITE); + gfx_FillRectangle_NoClip(x, KILL_COUNTER_INNER_Y, width, KILL_COUNTER_INNER_HEIGHT); + gfx_SetTextFGColor(COL_LIVES_TXT); + gfx_SetTextXY(x, KILL_COUNTER_INNER_Y + 4); + gfx_PrintUInt(kills, digits); +} + +void updateGameKillCounter(uint8_t kills, bool force) { + static uint8_t last = -1; + if(!force && last == kills) return; + last = kills; + gfx_SetDrawScreen(); + updateKillCounterCurrBuf(kills); + gfx_SetDrawBuffer(); + updateKillCounterCurrBuf(kills); +} + +void displayGameKillCounter(void) { + gfx_SetColor(COL_LIVES_TXT); // todo: add a bluer color + gfx_FillCircle_NoClip(KILL_COUNTER_END_X - KILL_COUNTER_RADIUS, KILL_COUNTER_Y + KILL_COUNTER_RADIUS, KILL_COUNTER_RADIUS); + gfx_FillRectangle_NoClip(0, KILL_COUNTER_Y, KILL_COUNTER_END_X - KILL_COUNTER_RADIUS, KILL_COUNTER_HEIGHT + 1); + + gfx_SetColor(COL_WHITE); + gfx_FillCircle_NoClip(KILL_COUNTER_INNER_END_X - KILL_COUNTER_INNER_RADIUS, KILL_COUNTER_INNER_Y + KILL_COUNTER_INNER_RADIUS - 1, KILL_COUNTER_INNER_RADIUS); + gfx_FillRectangle_NoClip(0, KILL_COUNTER_INNER_Y, KILL_COUNTER_INNER_END_X - KILL_COUNTER_INNER_RADIUS, KILL_COUNTER_INNER_HEIGHT); +} + +void displayGameBanner(uint8_t mission, uint8_t lives) { + // todo: check if the compiler optimizes these properly + const uint8_t banner_width = SCREEN_DELTA_X(10.5 * TILE_SIZE); + const uint8_t banner_height = 14; + const uint24_t base_x = (LCD_WIDTH - banner_width) / 2; + const uint8_t base_y = SCREEN_Y(LEVEL_SIZE_Y * TILE_SIZE - TILE_SIZE) + 3; + const uint8_t text_x = base_x + 18; + const uint24_t text2_x = base_x + 122; + const uint8_t text_y = base_y + 3; + const uint8_t rhomb_width = 7; + + gfx_SetColor(COL_RHOM_1); + gfx_HorizLine(base_x + 1, base_y, banner_width - 2); + gfx_HorizLine(base_x + 1, base_y + banner_height - 1, banner_width - 2); + gfx_FillRectangle_NoClip(base_x, base_y + 1, banner_width, banner_height - 2); + + gfx_SetColor(COL_RHOM_2); + for(uint24_t x = base_x; x < base_x + banner_width; x += rhomb_width) { + gfx_FillTriangle_NoClip(x, base_y + banner_height / 2 - 1, x + rhomb_width - 1, base_y + banner_height / 2 - 1, x + rhomb_width / 2, base_y); + gfx_FillTriangle_NoClip(x, base_y + banner_height / 2 - 1, x + rhomb_width - 1, base_y + banner_height / 2 - 1, x + rhomb_width / 2, base_y + banner_height - 1); + } + + gfx_SetTextXY(text_x + 1, text_y + 1); + gfx_SetTextFGColor(COL_TXT_SHADOW); + gfx_PrintString("Mission "); + gfx_PrintUInt(mission, 1); + gfx_SetTextXY(text2_x + 1, text_y + 1); + gfx_PrintString("x "); + gfx_PrintUInt(lives, 1); + + gfx_SetTextXY(text_x, text_y); + gfx_SetTextFGColor(COL_BG); + gfx_PrintString("Mission "); + gfx_PrintUInt(mission, 1); + gfx_SetTextXY(text2_x, text_y); + gfx_PrintString("x "); + gfx_PrintUInt(lives, 1); +} diff --git a/src/gui.h b/src/gui.h index 3e15268..c43892e 100644 --- a/src/gui.h +++ b/src/gui.h @@ -13,4 +13,8 @@ void displayKillCounts(void); void missionStartScreen(uint8_t mission, uint8_t lives, uint8_t num_tanks); //Display the mission start screen +void updateGameKillCounter(uint8_t kills, bool force); +void displayGameKillCounter(void); +void displayGameBanner(uint8_t mission, uint8_t lives); + #endif //TANKS_GUI_H diff --git a/src/mine.c b/src/mine.c index da6b621..2fd3bc4 100644 --- a/src/mine.c +++ b/src/mine.c @@ -31,7 +31,7 @@ void detonate(mine_t *mine) { MINE_EXPLOSION_RADIUS)) { tank->alive = false; game.kills[tanks[j].type]++; - game.total_kills++; + if(tanks[j].type != PLAYER) game.total_kills++; } for(k = 0; k < max_shells[tank->type]; k++) { shell_t* shell = &tank->shells[k]; diff --git a/src/shell.c b/src/shell.c index 3045716..d12f5a9 100644 --- a/src/shell.c +++ b/src/shell.c @@ -36,7 +36,7 @@ void processShell(shell_t* shell, tank_t* tank) { if(!tanks[j].alive) continue; if(detectCollision(&shell->phys, &tanks[j].phys)) { - game.total_kills++; + if(tanks[j].type != PLAYER) game.total_kills++; game.kills[tanks[j].type]++; tanks[j].alive = false; shell->alive = false;