From 227f2c15148ecc728ed6eebc65e984c106ae1322 Mon Sep 17 00:00:00 2001 From: David Maul <david.maul@informatik.hs-fulda.de> Date: Tue, 4 Feb 2025 20:56:30 +0100 Subject: [PATCH 1/3] add dpi aware scaling --- src/game/Engine.cpp | 19 +++++++++++++++++++ src/game/Engine.hpp | 4 ++++ src/game/Level.cpp | 18 ++++++++---------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/game/Engine.cpp b/src/game/Engine.cpp index 7639be5..14c638a 100644 --- a/src/game/Engine.cpp +++ b/src/game/Engine.cpp @@ -1,12 +1,14 @@ #include "Engine.hpp" #include "SDL_events.h" #include "SDL_timer.h" +#include "SDL_video.h" #include "Scene.hpp" #include "Spritesheet.hpp" #include "Window.hpp" #include <SDL.h> #include <SDL_image.h> #include <SDL_render.h> +#include <cmath> #include <deque> #include <memory> #include <optional> @@ -27,6 +29,23 @@ Engine::Engine(Window& window) : m_window(window), m_quit(false) } } +float Engine::getDPI() +{ + float ddpi; + if (SDL_GetDisplayDPI( + SDL_GetWindowDisplayIndex(this->m_window.sdl_window()), &ddpi, nullptr, nullptr) != 0) + { + throw std::runtime_error("SDL could not get DPI: " + std::string(SDL_GetError())); + } + + return ddpi; +} + +int Engine::getRenderingScale() +{ + return (int)std::round(this->getDPI() / 32.0); +} + std::deque<SDL_Event>& Engine::events() { return this->m_events; diff --git a/src/game/Engine.hpp b/src/game/Engine.hpp index 4ecbf8b..b3039e2 100644 --- a/src/game/Engine.hpp +++ b/src/game/Engine.hpp @@ -33,6 +33,10 @@ class Engine void pump(); + float getDPI(); + + int getRenderingScale(); + void pushScene(std::shared_ptr<Scene> scene); std::optional<std::shared_ptr<Scene>> popScene(); diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 67e35e5..7048fc4 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -17,8 +17,6 @@ namespace advanced_wars { -const int RENDERING_SCALE = 3; - Level::Level( std::string name, int width, int height, std::vector<Tile> tiles, std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects) @@ -190,8 +188,8 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) if (event.button.button == SDL_BUTTON_LEFT) { - int tileX = event.button.x / (16 * RENDERING_SCALE); - int tileY = event.button.y / (16 * RENDERING_SCALE); + int tileX = event.button.x / (16 * engine.getRenderingScale()); + int tileY = event.button.y / (16 * engine.getRenderingScale()); if (clickCheckLeft(tileX, tileY)) { @@ -220,8 +218,8 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) if (m_selectedUnit > -1) { - int tileX = event.button.x / (16 * RENDERING_SCALE); - int tileY = event.button.y / (16 * RENDERING_SCALE); + int tileX = event.button.x / (16 * engine.getRenderingScale()); + int tileY = event.button.y / (16 * engine.getRenderingScale()); if (clickCheckRight(tileX, tileY)) { @@ -291,19 +289,19 @@ void Level::render(Engine& engine) // Tiles for (Tile& tile : m_tiles) { - tile.render(engine, RENDERING_SCALE); + tile.render(engine, engine.getRenderingScale()); } // Buildings for (auto& [id, building] : m_buildings) { - building.render(engine, RENDERING_SCALE); + building.render(engine, engine.getRenderingScale()); } // Units for (auto& [id, unit] : m_units) { - unit.render(engine, RENDERING_SCALE); + unit.render(engine, engine.getRenderingScale()); } // Effects @@ -316,7 +314,7 @@ void Level::render(Engine& engine) } else { - effect.render(engine, RENDERING_SCALE); + effect.render(engine, engine.getRenderingScale()); } } -- GitLab From b9e20491fb69ee1cafd42adc156f0080827c0bf8 Mon Sep 17 00:00:00 2001 From: David Maul <david.maul@informatik.hs-fulda.de> Date: Tue, 4 Feb 2025 22:43:36 +0100 Subject: [PATCH 2/3] add scrolling if level is too large for window --- src/game/Building.cpp | 6 +++--- src/game/Building.hpp | 2 +- src/game/Effect.cpp | 6 +++--- src/game/Effect.hpp | 2 +- src/game/Engine.cpp | 15 ++++++++++---- src/game/Engine.hpp | 7 +++++-- src/game/Level.cpp | 47 +++++++++++++++++++++++++++++++++++++------ src/game/Level.hpp | 3 +++ src/game/Tile.cpp | 6 +++--- src/game/Tile.hpp | 2 +- src/game/Unit.cpp | 20 +++++++++--------- src/game/Unit.hpp | 4 ++-- 12 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/game/Building.cpp b/src/game/Building.cpp index efa12b6..7231d96 100644 --- a/src/game/Building.cpp +++ b/src/game/Building.cpp @@ -7,7 +7,7 @@ namespace advanced_wars Building::Building(int x, int y, BuildingId id, BuildingFaction faction) : m_x(x), m_y(y), m_id(id), m_faction(faction) {}; -void Building::render(Engine& engine, int scale) +void Building::render(Engine& engine, int scale, int offset_x, int offset_y) { Spritesheet* spritesheet = engine.getSpritesheet(); @@ -18,8 +18,8 @@ void Building::render(Engine& engine, int scale) src.h = spritesheet->getBuildingHeight(); SDL_Rect dst; - dst.x = m_x * spritesheet->getTileWidth() * scale; - dst.y = (m_y - 1) * spritesheet->getTileHeight() * scale; + dst.x = m_x * spritesheet->getTileWidth() * scale + offset_x; + dst.y = (m_y - 1) * spritesheet->getTileHeight() * scale + offset_y; dst.w = spritesheet->getBuildingWidth() * scale; dst.h = spritesheet->getBuildingHeight() * scale; diff --git a/src/game/Building.hpp b/src/game/Building.hpp index 031c315..d286ddd 100644 --- a/src/game/Building.hpp +++ b/src/game/Building.hpp @@ -35,7 +35,7 @@ class Building BuildingId m_id; BuildingFaction m_faction; - void render(Engine& engine, int scale); + void render(Engine& engine, int scale, int offset_x, int offset_y); }; } // namespace advanced_wars \ No newline at end of file diff --git a/src/game/Effect.cpp b/src/game/Effect.cpp index bb9a39b..76a155c 100644 --- a/src/game/Effect.cpp +++ b/src/game/Effect.cpp @@ -10,7 +10,7 @@ Effect::Effect(int x, int y, EffectId id, bool repeat) }; -void Effect::render(Engine& engine, int scale) +void Effect::render(Engine& engine, int scale, int offset_x, int offset_y) { Spritesheet* spritesheet = engine.getSpritesheet(); if (m_start == 0) @@ -28,8 +28,8 @@ void Effect::render(Engine& engine, int scale) src.h = spritesheet->getEffectHeight(); SDL_Rect dest; - dest.x = (m_x * spritesheet->getTileWidth() * scale) - 8; - dest.y = (m_y * spritesheet->getTileHeight() * scale) - 8; + dest.x = (m_x * spritesheet->getTileWidth() * scale) - 8 + offset_x; + dest.y = (m_y * spritesheet->getTileHeight() * scale) - 8 + offset_y; dest.w = spritesheet->getEffectWidth() * scale; dest.h = spritesheet->getEffectHeight() * scale; diff --git a/src/game/Effect.hpp b/src/game/Effect.hpp index e899c55..c39c39d 100644 --- a/src/game/Effect.hpp +++ b/src/game/Effect.hpp @@ -19,7 +19,7 @@ class Effect public: Effect(int x, int y, EffectId id, bool repeat); - void render(Engine& engine, int scale); + void render(Engine& engine, int scale, int offset_x, int offset_y); bool is_finished(Engine& engine); diff --git a/src/game/Engine.cpp b/src/game/Engine.cpp index 14c638a..c01436a 100644 --- a/src/game/Engine.cpp +++ b/src/game/Engine.cpp @@ -27,10 +27,7 @@ Engine::Engine(Window& window) : m_window(window), m_quit(false) { throw std::runtime_error("SDL could not generate renderer: " + std::string(SDL_GetError())); } -} -float Engine::getDPI() -{ float ddpi; if (SDL_GetDisplayDPI( SDL_GetWindowDisplayIndex(this->m_window.sdl_window()), &ddpi, nullptr, nullptr) != 0) @@ -38,7 +35,12 @@ float Engine::getDPI() throw std::runtime_error("SDL could not get DPI: " + std::string(SDL_GetError())); } - return ddpi; + this->m_ddpi = ddpi; +} + +float Engine::getDPI() +{ + return m_ddpi; } int Engine::getRenderingScale() @@ -46,6 +48,11 @@ int Engine::getRenderingScale() return (int)std::round(this->getDPI() / 32.0); } +Window& Engine::getWindow() +{ + return m_window; +} + std::deque<SDL_Event>& Engine::events() { return this->m_events; diff --git a/src/game/Engine.hpp b/src/game/Engine.hpp index b3039e2..7bf118b 100644 --- a/src/game/Engine.hpp +++ b/src/game/Engine.hpp @@ -53,6 +53,8 @@ class Engine void render(); + Window& getWindow(); + SDL_Renderer* renderer(); ~Engine(); @@ -64,8 +66,9 @@ class Engine std::optional<Spritesheet*> m_spritesheet; std::deque<SDL_Event> m_events; - bool m_quit; - int m_stage; + bool m_quit; + int m_stage; + float m_ddpi; }; } // namespace advanced_wars diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 7048fc4..15a7b1c 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -2,6 +2,7 @@ #include "Building.hpp" #include "Effect.hpp" #include "Engine.hpp" +#include "SDL_keycode.h" #include "Spritesheet.hpp" #include "Unit.hpp" #include "highfive/H5File.hpp" @@ -20,8 +21,8 @@ namespace advanced_wars Level::Level( std::string name, int width, int height, std::vector<Tile> tiles, std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects) - : m_name(name), m_width(width), m_height(height), m_tiles(tiles), m_contextMenu(ContextMenu()), - m_contextMenuActive(false), m_id(0) + : m_name(name), m_width(width), m_height(height), m_offset_x(0), m_offset_y(0), m_tiles(tiles), + m_contextMenu(ContextMenu()), m_contextMenuActive(false), m_id(0) { m_contextMenu.setOptions({"Move", "Info", "Wait"}); @@ -257,6 +258,40 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) PauseMenu pauseMenu(0, currentTexture); engine.pushScene(std::make_shared<PauseMenu>(pauseMenu)); } + if (event.key.keysym.sym == SDLK_w) + { + + m_offset_y += engine.getRenderingScale(); + m_offset_y = std::clamp( + m_offset_y, + std::min(0, engine.getWindow().h() - (engine.getRenderingScale() * m_height * 16)), + 0); + } + if (event.key.keysym.sym == SDLK_s) + { + m_offset_y -= engine.getRenderingScale(); + m_offset_y = std::clamp( + m_offset_y, + std::min(0, engine.getWindow().h() - (engine.getRenderingScale() * m_height * 16)), + 0); + } + if (event.key.keysym.sym == SDLK_a) + { + m_offset_x += engine.getRenderingScale(); + m_offset_x = std::clamp( + m_offset_x, + std::min(0, engine.getWindow().w() - (engine.getRenderingScale() * m_width * 16)), + 0); + } + if (event.key.keysym.sym == SDLK_d) + { + m_offset_x -= engine.getRenderingScale(); + m_offset_x = std::clamp( + m_offset_x, + std::min(0, engine.getWindow().w() - (engine.getRenderingScale() * m_width * 16)), + 0); + } + if (m_contextMenuActive) { if (event.key.keysym.sym == SDLK_RETURN) @@ -289,19 +324,19 @@ void Level::render(Engine& engine) // Tiles for (Tile& tile : m_tiles) { - tile.render(engine, engine.getRenderingScale()); + tile.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Buildings for (auto& [id, building] : m_buildings) { - building.render(engine, engine.getRenderingScale()); + building.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Units for (auto& [id, unit] : m_units) { - unit.render(engine, engine.getRenderingScale()); + unit.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Effects @@ -314,7 +349,7 @@ void Level::render(Engine& engine) } else { - effect.render(engine, engine.getRenderingScale()); + effect.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } } diff --git a/src/game/Level.hpp b/src/game/Level.hpp index 49c076f..a5e6ac2 100644 --- a/src/game/Level.hpp +++ b/src/game/Level.hpp @@ -48,6 +48,9 @@ class Level : public Scene int m_width; int m_height; + int m_offset_x; + int m_offset_y; + std::vector<Tile> m_tiles; std::unordered_map<int, Building> m_buildings; std::unordered_map<int, Unit> m_units; diff --git a/src/game/Tile.cpp b/src/game/Tile.cpp index bf393db..e4ca646 100644 --- a/src/game/Tile.cpp +++ b/src/game/Tile.cpp @@ -7,7 +7,7 @@ namespace advanced_wars Tile::Tile(TileId id, int x, int y) : m_id(id), m_x(x), m_y(y) {} -void Tile::render(Engine& engine, int scale) +void Tile::render(Engine& engine, int scale, int offset_x, int offset_y) { Spritesheet* spritesheet = engine.getSpritesheet(); @@ -20,8 +20,8 @@ void Tile::render(Engine& engine, int scale) src.h = spritesheet->getTileHeight(); SDL_Rect dest; - dest.x = m_x * spritesheet->getTileWidth() * scale; - dest.y = m_y * spritesheet->getTileHeight() * scale; + dest.x = m_x * spritesheet->getTileWidth() * scale + offset_x; + dest.y = m_y * spritesheet->getTileHeight() * scale + offset_y; dest.w = spritesheet->getTileWidth() * scale; dest.h = spritesheet->getTileHeight() * scale; diff --git a/src/game/Tile.hpp b/src/game/Tile.hpp index 44611fa..c1efc15 100644 --- a/src/game/Tile.hpp +++ b/src/game/Tile.hpp @@ -48,7 +48,7 @@ class Tile int m_x; int m_y; - void render(Engine& engine, int scale); + void render(Engine& engine, int scale, int offset_x, int offset_y); }; } // namespace advanced_wars \ No newline at end of file diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index fa90d0a..eace79d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -18,7 +18,7 @@ Unit::Unit(int x, int y, UnitFaction faction, UnitId id, UnitState state) m_health = m_maxHealth; } -void Unit::render(Engine& engine, int scale) +void Unit::render(Engine& engine, int scale, int offset_x, int offset_y) { Spritesheet* spritesheet = engine.getSpritesheet(); @@ -38,8 +38,8 @@ void Unit::render(Engine& engine, int scale) src.h = spritesheet->getUnitHeight(); SDL_Rect dst; - dst.x = m_x * spritesheet->getUnitWidth() * scale; - dst.y = m_y * spritesheet->getUnitHeight() * scale; + dst.x = m_x * spritesheet->getUnitWidth() * scale + offset_x; + dst.y = m_y * spritesheet->getUnitHeight() * scale + offset_y; dst.w = spritesheet->getUnitWidth() * scale; dst.h = spritesheet->getUnitHeight() * scale; @@ -63,8 +63,8 @@ void Unit::render(Engine& engine, int scale) src.h = spritesheet->getUnitMovingHeight(); SDL_Rect dst; - dst.x = ((m_x * spritesheet->getUnitWidth()) - 4) * scale; - dst.y = ((m_y * spritesheet->getUnitHeight()) - 8) * scale; + dst.x = ((m_x * spritesheet->getUnitWidth()) - 4) * scale + offset_x; + dst.y = ((m_y * spritesheet->getUnitHeight()) - 8) * scale + offset_y; dst.w = spritesheet->getUnitMovingWidth() * scale; dst.h = spritesheet->getUnitMovingHeight() * scale; @@ -77,7 +77,7 @@ void Unit::render(Engine& engine, int scale) .first, &src, &dst, 0, NULL, SDL_FLIP_NONE); } - renderHP(engine, scale); + renderHP(engine, scale, offset_x, offset_y); } void Unit::attack(Unit& enemy) @@ -217,7 +217,7 @@ bool Unit::inRange(Unit& enemy) return false; } -void Unit::renderHP(Engine& engine, int scale) +void Unit::renderHP(Engine& engine, int scale, int offset_x, int offset_y) { Spritesheet* spritesheet = engine.getSpritesheet(); @@ -234,8 +234,8 @@ void Unit::renderHP(Engine& engine, int scale) src.h = numberHeight; SDL_Rect dest; - dest.x = (m_x * spritesheet->getTileWidth() + 8) * scale; - dest.y = (m_y * spritesheet->getTileHeight() + 12) * scale; + dest.x = (m_x * spritesheet->getTileWidth() + 8) * scale + offset_x; + dest.y = (m_y * spritesheet->getTileHeight() + 12) * scale + offset_y; dest.w = numberWidth * scale; dest.h = numberHeight * scale; @@ -245,7 +245,7 @@ void Unit::renderHP(Engine& engine, int scale) { src.x = 8; - dest.x = (m_x * spritesheet->getTileWidth() + 1) * scale; + dest.x = (m_x * spritesheet->getTileWidth() + 1) * scale + offset_x; SDL_RenderCopy(engine.renderer(), numbers, &src, &dest); } diff --git a/src/game/Unit.hpp b/src/game/Unit.hpp index ba86a84..915a12d 100644 --- a/src/game/Unit.hpp +++ b/src/game/Unit.hpp @@ -75,7 +75,7 @@ class Unit // Assuming that the destruktion of a unit triggers events } - void render(Engine& engine, int scale); + void render(Engine& engine, int scale, int offset_x, int offset_y); /* Check if attacker is in Range to initiate combat @@ -136,7 +136,7 @@ class Unit int m_ammo; - void renderHP(Engine& engine, int scale); + void renderHP(Engine& engine, int scale, int offset_x, int offset_y); }; } // namespace advanced_wars \ No newline at end of file -- GitLab From f6dd2db87445a5ef2e4cda45a5c1a8e95156e90a Mon Sep 17 00:00:00 2001 From: David Maul <david.maul@informatik.hs-fulda.de> Date: Thu, 6 Feb 2025 02:02:22 +0100 Subject: [PATCH 3/3] hopefully fix dpi fetching --- src/game/Engine.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/game/Engine.cpp b/src/game/Engine.cpp index c01436a..fc938ef 100644 --- a/src/game/Engine.cpp +++ b/src/game/Engine.cpp @@ -1,5 +1,6 @@ #include "Engine.hpp" #include "SDL_events.h" +#include "SDL_rect.h" #include "SDL_timer.h" #include "SDL_video.h" #include "Scene.hpp" @@ -10,6 +11,7 @@ #include <SDL_render.h> #include <cmath> #include <deque> +#include <iostream> #include <memory> #include <optional> #include <stdexcept> @@ -32,7 +34,21 @@ Engine::Engine(Window& window) : m_window(window), m_quit(false) if (SDL_GetDisplayDPI( SDL_GetWindowDisplayIndex(this->m_window.sdl_window()), &ddpi, nullptr, nullptr) != 0) { - throw std::runtime_error("SDL could not get DPI: " + std::string(SDL_GetError())); + SDL_Rect size; + + if (SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(this->m_window.sdl_window()), &size) != + 0) + { + throw std::runtime_error( + "Even SDL_GetDisplayBounds fails, get a proper computer: " + + std::string(SDL_GetError())); + } + + float display_diagonal = 24.0; // 24 inch + + ddpi = std::hypot(size.w, size.h) / display_diagonal; + + std::cout << "Couldn't get DPI using fallback ddpi of " << ddpi << std::endl; } this->m_ddpi = ddpi; -- GitLab