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