diff --git a/src/game/Building.cpp b/src/game/Building.cpp index efa12b6c3c34b52730ba6be8a7a30329334d5c9f..7231d966c885519af49c556b1d40740642dc0809 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 031c315a6694823138ea96d5212e4a55ba576b40..d286ddd1d3023de07ce838f99a53f623dc026f6c 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 bb9a39b536254b856fb42b95f8876d409b175318..76a155cbdd43b47c4730eff48cf964427cbe4c19 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 e899c5567553a469c4944f84503012db2d1a0c6b..c39c39d4a655c0022a8dbaac84db99cebb293406 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 7639be52e31980ec8c331609f3adc119b7ba006f..fc938ef0f86e29bc02cc7a625c800fe31fc90db4 100644 --- a/src/game/Engine.cpp +++ b/src/game/Engine.cpp @@ -1,13 +1,17 @@ #include "Engine.hpp" #include "SDL_events.h" +#include "SDL_rect.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 <iostream> #include <memory> #include <optional> #include <stdexcept> @@ -25,6 +29,44 @@ Engine::Engine(Window& window) : m_window(window), m_quit(false) { throw std::runtime_error("SDL could not generate renderer: " + std::string(SDL_GetError())); } + + float ddpi; + if (SDL_GetDisplayDPI( + SDL_GetWindowDisplayIndex(this->m_window.sdl_window()), &ddpi, nullptr, nullptr) != 0) + { + 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; +} + +float Engine::getDPI() +{ + return m_ddpi; +} + +int Engine::getRenderingScale() +{ + return (int)std::round(this->getDPI() / 32.0); +} + +Window& Engine::getWindow() +{ + return m_window; } std::deque<SDL_Event>& Engine::events() diff --git a/src/game/Engine.hpp b/src/game/Engine.hpp index 4ecbf8bbdc98ed8ef4e4e4401c3323a3267051e6..7bf118bf243b376d15a30e6bba3b2165aa332a69 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(); @@ -49,6 +53,8 @@ class Engine void render(); + Window& getWindow(); + SDL_Renderer* renderer(); ~Engine(); @@ -60,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 67e35e591c155ab29412136997bb68770e1ba95b..15a7b1c14298e57d93b9543e5c1ad19ed23ace9d 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" @@ -17,13 +18,11 @@ 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) - : 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"}); @@ -190,8 +189,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 +219,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)) { @@ -259,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) @@ -291,19 +324,19 @@ void Level::render(Engine& engine) // Tiles for (Tile& tile : m_tiles) { - tile.render(engine, RENDERING_SCALE); + tile.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Buildings for (auto& [id, building] : m_buildings) { - building.render(engine, RENDERING_SCALE); + building.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Units for (auto& [id, unit] : m_units) { - unit.render(engine, RENDERING_SCALE); + unit.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } // Effects @@ -316,7 +349,7 @@ void Level::render(Engine& engine) } else { - effect.render(engine, RENDERING_SCALE); + effect.render(engine, engine.getRenderingScale(), m_offset_x, m_offset_y); } } diff --git a/src/game/Level.hpp b/src/game/Level.hpp index 49c076ff59608b86901d7253610bc55b8564b78a..a5e6ac21ca2cf259a6effcac4e06008d6797bb4f 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 bf393db7a961c13617e31b1f23768e330258a2bf..e4ca6466a42737b6b4d5947112abd37a9dfb7062 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 44611faab72f346c6df782e1fb4d7163834d914d..c1efc15522e4b45e19ebd4c9d5e28e1df44fffab 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 fa90d0a73ae20501103133e8b25494901e74ca84..eace79dcbc022bb02e2b39a261879b480a23245d 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 ba86a8499edf7024cd70d873dd39bbec424b892e..915a12de6932d76949d2f069c8bc7cbb57ec33d7 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