From 83ed7e5190de3151407beec1fadadcc206b4d628 Mon Sep 17 00:00:00 2001 From: Reimar Date: Tue, 4 Nov 2025 15:31:11 +0100 Subject: [PATCH] Implement font rendering, add gold --- Makefile | 4 ++-- src/Color.hpp | 28 ++++++++++++++++++++++++++++ src/Game.cpp | 18 ++++++++++++++++-- src/Game.hpp | 3 ++- src/GameRenderer.cpp | 32 +++++++++++++++++++++++++++++--- src/GameRenderer.hpp | 14 ++++++++++++-- src/Player.hpp | 2 ++ 7 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/Color.hpp diff --git a/Makefile b/Makefile index fbec4cf..b5588c7 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,8 @@ else LINKER_FLAGS += -fsanitize=address,undefined -g -Og -rdynamic endif -CXX_FLAGS += $(shell pkg-config sdl2 SDL2_image --cflags) -LINKER_FLAGS += $(shell pkg-config sdl2 SDL2_image --libs) +CXX_FLAGS += $(shell pkg-config sdl2 SDL2_image SDL2_ttf --cflags) +LINKER_FLAGS += $(shell pkg-config sdl2 SDL2_image SDL2_ttf --libs) build/%.o: %.cpp $(wildcard *.hpp) @mkdir -p `dirname $@` diff --git a/src/Color.hpp b/src/Color.hpp new file mode 100644 index 0000000..0d29e81 --- /dev/null +++ b/src/Color.hpp @@ -0,0 +1,28 @@ +#ifndef COLOR_HPP +#define COLOR_HPP + +#include + +typedef SDL_Color Color; + +inline Color rgb(uint8_t red, uint8_t green, uint8_t blue) +{ + SDL_Color color; + color.r = red; + color.g = green; + color.b = blue; + color.a = 255; + return color; +} + +inline Color rgba(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) +{ + SDL_Color color; + color.r = red; + color.g = green; + color.b = blue; + color.a = alpha; + return color; +} + +#endif diff --git a/src/Game.cpp b/src/Game.cpp index c902367..8c746c6 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,8 +1,10 @@ #include #include +#include #include "GameRenderer.hpp" #include "Player.hpp" #include "Game.hpp" +#include "Color.hpp" using namespace std::literals::chrono_literals; @@ -10,6 +12,9 @@ Game::Game() : renderer("Zombo Shooter", 800, 450), player(&renderer), map(&rend { arrow_sprite = renderer.load_sprite("./assets/arrow.png", 22, 8); zombo_sprite = renderer.load_sprite("./assets/zombo.png", 40, 40); + gold_sprite = renderer.load_sprite("./assets/gold.png", 30, 20); + + font = renderer.load_font("./assets/Jersey20-Regular.ttf", 26); } void Game::update(std::stop_token stop_token) @@ -53,7 +58,10 @@ void Game::update(std::stop_token stop_token) std::erase(arrows, arrow); zombo.hp--; - if (zombo.hp == 0) std::erase(zombos, zombo); + if (zombo.hp == 0) { + std::erase(zombos, zombo); + player.gold += 10; + } } } } @@ -76,7 +84,7 @@ void Game::draw() { const std::lock_guard lock(game_mutex); - renderer.clear_screen(0x80, 0x40, 0xFF, 0xFF); + renderer.clear_screen(rgb(0x80, 0x40, 0xFF)); map.draw(player.x, player.y); @@ -90,6 +98,12 @@ void Game::draw() player.draw(); + renderer.draw_sprite(*gold_sprite, renderer.screen_width - 50, 10); + + int text_width = renderer.get_text_width(font, std::to_string(player.gold)); + renderer.draw_text(font, std::to_string(player.gold), renderer.screen_width - gold_sprite->width - text_width - 28, 10, rgb(0, 0, 0)); + renderer.draw_text(font, std::to_string(player.gold), renderer.screen_width - gold_sprite->width - text_width - 30, 8, rgb(255, 255, 255)); + renderer.flush(); } diff --git a/src/Game.hpp b/src/Game.hpp index e949e43..db38560 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -17,7 +17,8 @@ private: Map map; std::vector arrows; std::vector zombos; - std::unique_ptr arrow_sprite, zombo_sprite; + std::unique_ptr arrow_sprite, zombo_sprite, gold_sprite; + Font *font; std::mutex game_mutex; unsigned int ticks = 0; diff --git a/src/GameRenderer.cpp b/src/GameRenderer.cpp index 379b15f..ec1f1a1 100644 --- a/src/GameRenderer.cpp +++ b/src/GameRenderer.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #include #include #include "Sprite.hpp" @@ -12,6 +13,11 @@ GameRenderer::GameRenderer(const std::string &title, const int screen_width, con exit(EXIT_FAILURE); } + if (TTF_Init() < 0) { + std::cerr << "Unable to initialize SDL_ttf" << std::endl; + exit(EXIT_FAILURE); + } + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); window = SDL_CreateWindow( @@ -40,6 +46,26 @@ GameRenderer::~GameRenderer() SDL_DestroyWindow(window); } +Font *GameRenderer::load_font(const std::string &file, int font_size) +{ + return TTF_OpenFont(file.c_str(), font_size); +} + +int GameRenderer::get_text_width(Font *font, const std::string &text) const +{ + SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), rgb(0, 0, 0)); + return surface->w; +} + +void GameRenderer::draw_text(Font *font, const std::string &text, int x, int y, Color color) const +{ + SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), color); + SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); + + SDL_Rect textRect = { .x = x, .y = y, .w = surface->w, .h = surface->h }; + SDL_RenderCopy(renderer, texture, nullptr, &textRect); +} + std::unique_ptr GameRenderer::load_sprite(const std::string &file, const int width, const int height) const { return std::make_unique(renderer, file, width, height); @@ -63,9 +89,9 @@ void GameRenderer::draw_sprite_rotated(const Sprite &sprite, const int x, const SDL_RenderCopyEx(renderer, sprite.texture, nullptr, &rect, angle, nullptr, SDL_FLIP_NONE); } -void GameRenderer::clear_screen(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a) const +void GameRenderer::clear_screen(Color color) const { - SDL_SetRenderDrawColor(renderer, r, g, b, a); + SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); SDL_RenderClear(renderer); } diff --git a/src/GameRenderer.hpp b/src/GameRenderer.hpp index afe9c35..4254716 100644 --- a/src/GameRenderer.hpp +++ b/src/GameRenderer.hpp @@ -4,7 +4,11 @@ #include #include #include +#include #include "Sprite.hpp" +#include "Color.hpp" + +typedef TTF_Font Font; class GameRenderer { @@ -22,7 +26,13 @@ public: ~GameRenderer(); - std::unique_ptr load_sprite(const std::string &file, int width, int height) const; + [[nodiscard]] Font *load_font(const std::string &file, int font_size); + + int get_text_width(Font *font, const std::string &text) const; + + void draw_text(Font *font, const std::string &text, int x, int y, Color color) const; + + [[nodiscard]] std::unique_ptr load_sprite(const std::string &file, int width, int height) const; void draw_sprite(const Sprite &sprite, int x, int y) const; @@ -30,7 +40,7 @@ public: void draw_sprite_rotated(const Sprite &sprite, int x, int y, double angle) const; - void clear_screen(uint8_t r, uint8_t g, uint8_t b, uint8_t a) const; + void clear_screen(Color color) const; void flush() const; diff --git a/src/Player.hpp b/src/Player.hpp index 7333671..0a71e22 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -21,6 +21,8 @@ public: int shooting_cooldown = 0; + int gold = 0; + static constexpr double speed = 1.5; Player(GameRenderer *renderer);