Jelajahi Sumber

Starting work on TileMap rendering

Vitaliy Polonski 5 jam lalu
induk
melakukan
0a329a6008

+ 1 - 0
CMakeLists.txt

@@ -58,6 +58,7 @@ add_executable(kariokaEngine
 	src/tiles/Chunk.cpp
 	src/tiles/TileMap.cpp
 	src/tiles/TileMapManager.cpp
+	src/tiles/TileRenderer.cpp
 )
 
 target_link_libraries(kariokaEngine PRIVATE

+ 4 - 0
src/Engine.cpp

@@ -18,6 +18,10 @@ Engine::Engine()
     InitImGui();
     InitAudio();
     InitPython();
+
+    // TileMapManager
+    tileMapManager.CreateMap("overworld", 32, 32);
+    tileMapManager.CreateMap("dungeon", 16, 16);
     
     // Load assets ...
     

+ 8 - 0
src/Engine.h

@@ -11,6 +11,7 @@
 #include "states/StateManager.h"
 #include <pybind11/embed.h>
 #include "ui/PythonConsole.h"
+#include "tiles/TileMapManager.h"
 
 namespace py = pybind11;
 
@@ -43,6 +44,10 @@ public:
     void RequestStateChange(std::unique_ptr<BaseState> newState);
     void RequestPopState();
     
+    // TileMapManager
+    TileMapManager& GetTileMapManager() { return tileMapManager; }
+    const TileMapManager& GetTileMapManager() const { return tileMapManager; }
+    
     // Debug
     void DebugInfo();
     
@@ -70,6 +75,9 @@ private:
     // StateManager
     std::unique_ptr<BaseState> pendingNewState = nullptr;
     bool pendingPop = false;
+    
+    // TileMapManager
+    TileMapManager tileMapManager;
 
 };
 

+ 43 - 5
src/scripting/bindings/kariokaModule.cpp

@@ -4,6 +4,7 @@
 #include "../../Engine.h"
 #include <SDL2/SDL_log.h>
 #include <iostream>
+#include "../../tiles/TileMapManager.h"
 
 namespace py = pybind11;
 
@@ -13,7 +14,7 @@ PYBIND11_EMBEDDED_MODULE(karioka, m)
 {
     m.doc() = "kariokaEngine Python API";
     
-    // Bind the Engine class
+    // --- Bind the Engine class ----------------------------------------------------
     py::class_<Engine, std::unique_ptr<Engine, py::nodelete>> engine_cls(m, "Engine");
     
     // Bind useful methods from Engine
@@ -21,7 +22,7 @@ PYBIND11_EMBEDDED_MODULE(karioka, m)
     engine_cls.def("StopRunning", &Engine::StopRunning);
     engine_cls.def("IsRunning", &Engine::IsRunning);
     
-    // State management
+    // --- State management ---------------------------------------------------------
     engine_cls.def("RequestStateChange", &Engine::RequestStateChange);
     engine_cls.def("RequestPopState", &Engine::RequestPopState);
     
@@ -49,16 +50,53 @@ PYBIND11_EMBEDDED_MODULE(karioka, m)
     m.def("get_states", []() -> py::list {
         return Engine::Get().GetStateStack();
     });
+
+    // --- TileMapManager -----------------------------------------------------------
+    engine_cls.def("GetTileMapManager", [](Engine& self) -> TileMapManager& {
+        return self.GetTileMapManager();
+    }, py::return_value_policy::reference);
+    
+    m.def("create_map", [](const std::string& name, int wChunks, int hChunks) {
+        Engine::Get().GetTileMapManager().CreateMap(name, wChunks, hChunks);
+    });
+    
+    m.def("switch_map", [](const std::string& name) {
+        return Engine::Get().GetTileMapManager().SetCurrentMap(name);
+    });
+    
+    m.def("set_tile", [](int worldX, int worldY, uint32_t tileId) {
+        auto* currentMap = Engine::Get().GetTileMapManager().GetCurrentMap();
+        if (currentMap)
+        {
+            Tile tile;
+            tile.tileId = tileId;
+            currentMap->SetTile(worldX, worldY, tile);
+        }
+    });
+    
+    m.def("get_tile_id", [](int worldX, int worldY) -> uint32_t {
+        auto* currentMap = Engine::Get().GetTileMapManager().GetCurrentMap();
+        if (currentMap)
+        {
+            const Tile* tile = currentMap->GetTile(worldX, worldY);
+            if (!tile)
+            {
+                return 0;
+            }
+            return tile->tileId;
+        }
+        return 0;
+    });
     
-    // Logging
+    // --- Logging ------------------------------------------------------------------
     engine_cls.def("log",  [](Engine& self, const std::string& msg) {
         SDL_Log("[PY] %s", msg.c_str());
     });
     
-    // Static accessor
+    // --- Static accessor ---------------------------------------------------------
     engine_cls.def_static("get", &Engine::Get, py::return_value_policy::reference);
 
-    // === Convenient top-level functions ==
+    // --- Convenient top-level functions ------------------------------------------
     m.def("engine", &Engine::Get, py::return_value_policy::reference);
     
     m.def("log", [](const std::string& msg) {

+ 75 - 0
src/tiles/TileRenderer.cpp

@@ -0,0 +1,75 @@
+#include "TileRenderer.h"
+#include <iostream>
+
+TileRenderer::TileRenderer(SDL_Renderer* renderer) : renderer(renderer)
+{
+}
+
+void TileRenderer::SetTileset(SDL_Texture* texture, int tileSizePx)
+{
+    tileset = texture;
+    tileSize = tileSizePx;
+}
+
+void TileRenderer::RenderVisibleChunks(TileMap* map,
+                                       int cameraX, int cameraY,
+                                       int screenWidth, int screenHeight)
+{
+    if (!map || !tileset || !renderer)
+    {
+        return;
+    }
+    
+    auto visibleChunks = map->GetVisibleChunks(cameraX, cameraY, screenWidth, screenHeight);
+    
+    for (Chunk* chunk : visibleChunks)
+    {
+        if (!chunk)
+        {
+            continue;
+        }
+        
+        int chunkWorldX = chunk->chunkX * CHUNK_SIZE * tileSize;
+        int chunkWorldY = chunk->chunkY * CHUNK_SIZE * tileSize;
+        
+        // Draw TileMap
+        // TODO: Add layers to chunks later
+        for (int ly = 0; ly < CHUNK_SIZE; ++ly)
+        {
+            for (int lx = 0; lx < CHUNK_SIZE; ++lx)
+            {
+                const Tile& tile = chunk->GetTile(lx, ly);
+                if (tile.tileId == 0) // Do not draw tile with id 0
+                {
+                    continue;
+                }
+                
+                int screenX = chunkWorldX + lx * tileSize - cameraX;
+                int screenY = chunkWorldY + ly * tileSize - cameraY;
+                
+                // Simple culling
+                if (screenX + tileSize < 0 || screenX > screenWidth ||
+                    screenY + tileSize < 0 || screenY > screenHeight)
+                {
+                    continue;
+                }
+                
+                // Assuming 16 tiles per row
+                int srcX = static_cast<int>(tile.tileId % 16) * tileSize;
+                int srcY = static_cast<int>(tile.tileId / 16) * tileSize;
+                
+                SDL_Rect srcRect = {               // Get tile from tileset
+                    srcX, srcY, 
+                    tileSize, tileSize
+                };
+                
+                SDL_Rect dstRect = {               // Put tile into screen
+                    screenX, screenY,
+                    tileSize, tileSize
+                };
+                
+                SDL_RenderCopy(renderer, tileset, &srcRect, &dstRect);
+            }
+        }
+    }
+}

+ 25 - 0
src/tiles/TileRenderer.h

@@ -0,0 +1,25 @@
+#ifndef __TILES__TILE_RENDERER_H__
+#define __TILES__TILE_RENDERER_H__
+
+#include "TileMap.h"
+#include <SDL2/SDL.h>
+
+class TileRenderer
+{
+public:
+    TileRenderer(SDL_Renderer* renderer);
+    
+    void SetTileset(SDL_Texture* tilesetTexture, int tileSizePx = 32);
+    
+    void RenderVisibleChunks(TileMap* map,
+                             int cameraX, int cameraY,
+                             int screenWidth, int screenHeight);
+
+private:
+    SDL_Renderer* renderer = nullptr;
+    SDL_Texture* tileset = nullptr;
+    int tileSize = 32;
+
+};
+
+#endif