Implement resource server

This commit is contained in:
Lexi / Zoe 2026-06-16 21:53:19 +02:00
parent 3addd01f54
commit 718679c13b
Signed by: binaryDiv
GPG key ID: F8D4956E224DA232
14 changed files with 332 additions and 232 deletions

View file

@ -0,0 +1,12 @@
module;
export module rutile.core.common;
import std;
export namespace rutile
{
// Alias for shared_ptr to be used for shared resource pointers (see ResourceServer)
template <typename T>
using ResourcePtr = std::shared_ptr<T>;
}

View file

@ -5,15 +5,17 @@ module;
export module rutile.core.drawing.sprite; export module rutile.core.drawing.sprite;
import std; import std;
import rutile.core.common;
import rutile.core.render_server; import rutile.core.render_server;
import rutile.core.resources.texture;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile
{ {
class Sprite class Sprite
{ {
// Texture ID (managed by TextureManager in RenderServer) // Shared pointer to a texture (managed by ResourceServer)
TextureID texture_id_; ResourcePtr<Texture> texture_ptr_;
// Texture source boundaries: which part of the texture to render // Texture source boundaries: which part of the texture to render
sdl::FRect texture_boundaries_; sdl::FRect texture_boundaries_;
@ -30,13 +32,13 @@ export namespace rutile
public: public:
explicit Sprite( explicit Sprite(
const TextureID texture_id, const ResourcePtr<Texture>& texture_ptr,
const sdl::FRect texture_boundaries, const sdl::FRect texture_boundaries,
const sdl::FPoint position, const sdl::FPoint position,
const sdl::FPoint texture_offset = {0, 0}, const sdl::FPoint texture_offset = {0, 0},
const sdl::FPoint texture_scale = {1, 1} const sdl::FPoint texture_scale = {1, 1}
) )
: texture_id_{texture_id}, : texture_ptr_{texture_ptr},
texture_boundaries_{texture_boundaries}, texture_boundaries_{texture_boundaries},
texture_offset_{texture_offset}, texture_offset_{texture_offset},
texture_scale_{texture_scale}, texture_scale_{texture_scale},
@ -46,20 +48,16 @@ export namespace rutile
} }
static Sprite create_from_texture( static Sprite create_from_texture(
RenderServer& render_server, const ResourcePtr<Texture>& texture_ptr,
const std::string& filename,
std::optional<sdl::FRect> texture_boundaries, std::optional<sdl::FRect> texture_boundaries,
auto... args auto... args
) )
{ {
const TextureID texture_id = render_server.load_texture(filename);
if (!texture_boundaries.has_value()) { if (!texture_boundaries.has_value()) {
const sdl::Texture& texture = render_server.get_texture(texture_id); texture_boundaries = texture_ptr->get_boundaries();
texture_boundaries = texture.get_boundaries();
} }
return Sprite(texture_id, texture_boundaries.value(), args...); return Sprite(texture_ptr, texture_boundaries.value(), args...);
} }
void set_position(const sdl::FPoint new_position) void set_position(const sdl::FPoint new_position)
@ -76,7 +74,7 @@ export namespace rutile
texture_scale_.y * texture_boundaries_.h, texture_scale_.y * texture_boundaries_.h,
}; };
render_server.render_texture(texture_id_, &texture_boundaries_, &dest_rect); render_server.render_texture(*texture_ptr_, &texture_boundaries_, &dest_rect);
} }
}; };
} }

View file

@ -5,8 +5,9 @@ module;
export module rutile.core.drawing.tile_map; export module rutile.core.drawing.tile_map;
import std; import std;
import rutile.core.drawing.tile_set; import rutile.core.common;
import rutile.core.render_server; import rutile.core.render_server;
import rutile.core.resources.tile_set;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile
@ -16,10 +17,8 @@ export namespace rutile
class TileMap class TileMap
{ {
// Tile set ID // Shared pointer to a tile set (managed by ResourceServer)
// TODO: Needed later when we centralize tile set management using a ResourceManager ResourcePtr<TileSet> tile_set_ptr_;
[[maybe_unused]]
TileSetID tile_set_id_;
// Tile size // Tile size
int tile_size_; int tile_size_;
@ -36,16 +35,16 @@ export namespace rutile
public: public:
explicit TileMap( explicit TileMap(
const TileSetID tile_set_id, const ResourcePtr<TileSet>& tile_set_ptr,
const int tile_size, const int tile_size,
const MapCoord width, const MapCoord width,
const MapCoord height, const MapCoord height,
const sdl::FPoint position = {0, 0} const sdl::FPoint position = {0, 0}
) )
: tile_set_id_(tile_set_id), : tile_set_ptr_{tile_set_ptr},
tile_size_(tile_size), tile_size_{tile_size},
width_(width), width_{width},
height_(height), height_{height},
position_{position} position_{position}
{ {
// TODO: This maybe shouldn't be an assert... // TODO: This maybe shouldn't be an assert...
@ -72,11 +71,9 @@ export namespace rutile
tiles_[map_coords_to_index(x, y)] = tile_id; tiles_[map_coords_to_index(x, y)] = tile_id;
} }
// TODO: Should we get the TileSet from the RenderServer, similar to how we get textures? void draw(const RenderServer& render_server) const
void draw(const RenderServer& render_server, const TileSet& tile_set) const
{ {
// Get tile set texture const TileSet& tile_set = *tile_set_ptr_;
const sdl::Texture& tile_set_texture = render_server.get_texture(tile_set.get_texture_id());
// TODO: Implement more efficiently (we could just iterate over tiles_ directly) // TODO: Implement more efficiently (we could just iterate over tiles_ directly)
for (MapCoord y = 0; y < height_; y++) { for (MapCoord y = 0; y < height_; y++) {
@ -97,7 +94,7 @@ export namespace rutile
}; };
render_server.render_texture( render_server.render_texture(
tile_set_texture, tile_set.get_texture(),
&tile_atlas_src_rect, &tile_atlas_src_rect,
&tile_dest_rect &tile_dest_rect
); );

View file

@ -7,6 +7,7 @@ export module rutile.core.engine;
import std; import std;
import rutile.config; import rutile.config;
import rutile.core.render_server; import rutile.core.render_server;
import rutile.core.resource_server;
import rutile.core.ui.ui_server; import rutile.core.ui.ui_server;
import wrappers.sdl; import wrappers.sdl;
@ -22,12 +23,14 @@ export namespace rutile
sdl::Window window_; sdl::Window window_;
RenderServer render_server_; RenderServer render_server_;
ResourceServer resource_server_;
UIServer ui_server_; UIServer ui_server_;
// Private constructor // Private constructor
Engine(sdl::Window&& window, sdl::Renderer&& renderer) Engine(sdl::Window&& window, sdl::Renderer&& renderer)
: window_{std::move(window)}, : window_{std::move(window)},
render_server_{std::move(renderer)}, render_server_{std::move(renderer)},
resource_server_{render_server_.get_renderer()},
ui_server_{render_server_.get_renderer(), window_} ui_server_{render_server_.get_renderer(), window_}
{ {
instantiated_ = true; instantiated_ = true;
@ -84,6 +87,11 @@ export namespace rutile
return render_server_; return render_server_;
} }
ResourceServer& get_resource_server()
{
return resource_server_;
}
UIServer& get_ui_server() UIServer& get_ui_server()
{ {
return ui_server_; return ui_server_;

View file

@ -3,28 +3,21 @@ module;
export module rutile.core.render_server; export module rutile.core.render_server;
import std; import std;
import rutile.core.resource_manager; import rutile.core.resource_server;
import rutile.core.texture_loader; import rutile.core.resources.texture;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile
{ {
using TextureID = unsigned int;
using TextureManager = ResourceManager<TextureID, sdl::Texture, TextureLoader>;
class RenderServer class RenderServer
{ {
sdl::Renderer renderer_; sdl::Renderer renderer_;
TextureLoader texture_loader_;
TextureManager texture_manager_;
public: public:
RenderServer() = delete; RenderServer() = delete;
explicit RenderServer(sdl::Renderer&& renderer) explicit RenderServer(sdl::Renderer&& renderer)
: renderer_{std::move(renderer)}, : renderer_{std::move(renderer)}
texture_loader_{renderer_},
texture_manager_{texture_loader_}
{ {
renderer_.set_vsync(1); renderer_.set_vsync(1);
} }
@ -42,22 +35,6 @@ export namespace rutile
return renderer_; return renderer_;
} }
/**
* Load a texture from a file (if not loaded yet) and return its texture ID.
*/
constexpr TextureID load_texture(const std::string& filename)
{
return texture_manager_.load_resource_by_name(filename);
}
/**
* Get a reference to a texture by its texture ID.
*/
constexpr const sdl::Texture& get_texture(const TextureID texture_id) const
{
return texture_manager_.get_resource(texture_id);
}
void start_frame() const void start_frame() const
{ {
renderer_.clear(); renderer_.clear();
@ -68,17 +45,8 @@ export namespace rutile
renderer_.present(); renderer_.present();
} }
void render_texture(
const TextureID texture_id,
const sdl::FRect* src_rect,
const sdl::FRect* dest_rect
) const
{
render_texture(get_texture(texture_id), src_rect, dest_rect);
}
constexpr void render_texture( constexpr void render_texture(
const sdl::Texture& texture, const Texture& texture,
const sdl::FRect* src_rect, const sdl::FRect* src_rect,
const sdl::FRect* dest_rect const sdl::FRect* dest_rect
) const ) const

View file

@ -1,120 +0,0 @@
module;
#include <cassert>
export module rutile.core.resource_manager;
import std;
export namespace rutile
{
template <typename ResourceLoaderType, typename ResourceType>
concept IsResourceLoader = requires(ResourceLoaderType loader, const std::string& name)
{
{ loader.load_resource(name) } -> std::same_as<ResourceType>;
};
template <
typename ResourceIDType,
typename ResourceType,
IsResourceLoader<ResourceType> ResourceLoaderType
>
class ResourceManager
{
// Resource loader
ResourceLoaderType& resource_loader_;
// Registry of loaded resources, array index is resource ID
std::vector<ResourceType> resource_registry_;
// Mapping of all loaded resources from (file) name to resource ID
std::map<std::string, ResourceIDType> resource_name_map_;
public:
ResourceManager() = delete;
explicit ResourceManager(ResourceLoaderType& resource_loader)
: resource_loader_{resource_loader}
{}
// No copy or move operations
ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete;
ResourceManager(ResourceManager&&) = delete;
ResourceManager& operator=(ResourceManager&&) = delete;
~ResourceManager() = default;
/**
* Adds a new resource to the registry and returns its ID.
*/
ResourceIDType add_resource(ResourceType&& resource)
{
// Add resource to end of vector
resource_registry_.push_back(std::move(resource));
// Return the index of the newly added resource
return static_cast<ResourceIDType>(resource_registry_.size() - 1);
}
/**
* Adds a new resource to the registry, associates the name with it and returns its ID.
*/
ResourceIDType add_resource(ResourceType&& resource, const std::string& name)
{
// Add resource
ResourceIDType resource_id = add_resource(std::move(resource));
// Associate name with resource ID for future access
resource_name_map_.emplace(name, resource_id);
return resource_id;
}
/**
* Gets the resource ID for a given resource name, or `std::nullopt` if the resource was not found.
*/
std::optional<ResourceIDType> get_resource_id_by_name(const std::string& name) const
{
// Check if resource is already loaded
if (
const auto search = resource_name_map_.find(name);
search != resource_name_map_.end()
) {
// Return resource ID
return search->second;
}
return std::nullopt;
}
/**
* Loads a resource (e.g. from a file) and adds it to the registry if it isn't loaded yet.
* Returns the resource ID.
*/
ResourceIDType load_resource_by_name(const std::string& name)
{
// Check if resource is already loaded
if (
auto resource_id = get_resource_id_by_name(name);
resource_id.has_value()
) {
return resource_id.value();
}
// Load resource and add it to the registry
return add_resource(resource_loader_.load_resource(name), name);
}
/**
* Returns a reference to the resource with the given ID.
* The reference is not guaranteed to be valid after adding new resources to the registry.
* Assumes that the resource ID is valid.
*/
const ResourceType& get_resource(const ResourceIDType resource_id) const
{
assert(resource_id < resource_registry_.size());
return resource_registry_[resource_id];
}
};
}

View file

@ -0,0 +1,61 @@
module;
export module rutile.core.resource_server;
import std;
import rutile.core.common;
import rutile.core.resources.resource_registry;
import rutile.core.resources.texture;
import rutile.core.resources.tile_set;
import rutile.core.resources.loaders.texture_loader;
import rutile.core.resources.loaders.tile_set_loader;
import wrappers.sdl;
export namespace rutile
{
using TextureRegistry = ResourceRegistry<TextureID, Texture>;
using TileSetRegistry = ResourceRegistry<TileSetID, TileSet>;
class ResourceServer
{
// Resource registries
TextureRegistry texture_registry_;
TileSetRegistry tile_set_registry_;
// Resource loaders
TextureLoader texture_loader_;
TileSetLoader tile_set_loader_;
public:
ResourceServer() = delete;
explicit ResourceServer(sdl::Renderer& renderer)
: texture_loader_{renderer},
tile_set_loader_{std::bind(&ResourceServer::load_texture, this, std::placeholders::_1)}
{}
// No copy or move operations
ResourceServer(const ResourceServer&) = delete;
ResourceServer& operator=(const ResourceServer&) = delete;
ResourceServer(ResourceServer&&) = delete;
ResourceServer& operator=(ResourceServer&&) = delete;
~ResourceServer() = default;
/**
* Load a texture from a file (if not loaded yet) and return a reference to a shared Texture pointer.
*/
const ResourcePtr<Texture>& load_texture(const std::string& filename)
{
return texture_registry_.load_and_get_resource(filename, texture_loader_);
}
/**
* Load a tile set from a JSON file (if not loaded yet) and return a reference to a shared TileSet pointer.
*/
const ResourcePtr<TileSet>& load_tile_set(const std::string& filename)
{
return tile_set_registry_.load_and_get_resource(filename, tile_set_loader_);
}
};
}

View file

@ -1,9 +1,9 @@
module; module;
export module rutile.core.texture_loader; export module rutile.core.resources.loaders.texture_loader;
import std; import std;
import rutile.core.resource_manager; import rutile.core.resources.texture;
import wrappers.sdl; import wrappers.sdl;
import wrappers.sdl_image; import wrappers.sdl_image;
@ -26,7 +26,7 @@ export namespace rutile
~TextureLoader() = default; ~TextureLoader() = default;
sdl::Texture load_resource(const std::string& filename) const Texture load_resource(const std::string& filename) const
{ {
return sdl_image::load_texture(renderer_, filename); return sdl_image::load_texture(renderer_, filename);
} }

View file

@ -0,0 +1,57 @@
module;
export module rutile.core.resources.loaders.tile_set_loader;
import std;
import rutile.core.common;
import rutile.core.resources.texture;
import rutile.core.resources.tile_set;
// import vendor.nlohmann.json;
// using json = nlohmann::json;
namespace rutile
{
using TextureLoadCallbackFunc = std::function<
const ResourcePtr<Texture>&(const std::string&)
>;
}
export namespace rutile
{
class TileSetLoader
{
TextureLoadCallbackFunc texture_load_callback_;
public:
explicit TileSetLoader(const TextureLoadCallbackFunc& texture_load_callback)
: texture_load_callback_{texture_load_callback}
{}
// No copy or move operations (reference)
TileSetLoader(const TileSetLoader&) = delete;
TileSetLoader& operator=(const TileSetLoader&) = delete;
TileSetLoader(TileSetLoader&&) = delete;
TileSetLoader& operator=(TileSetLoader&&) = delete;
~TileSetLoader() = default;
TileSet load_resource(const std::string& name) const
{
return TileSet::create_from_texture(
texture_load_callback_(name),
// TODO: Load this from a JSON file
32,
{
// Tile 0: No tile
{0, 0},
// Tile 1: Actual first tile in the texture
{0, 0},
{1, 0},
{2, 0},
{3, 0},
}
);
}
};
}

View file

@ -0,0 +1,128 @@
module;
#include <cassert>
export module rutile.core.resources.resource_registry;
import std;
import rutile.core.common;
export namespace rutile
{
template <typename ResourceLoaderType, typename ResourceType>
concept IsResourceLoader = requires(ResourceLoaderType loader, const std::string& name)
{
{ loader.load_resource(name) } -> std::same_as<ResourceType>;
};
template <typename ResourceIDType, typename ResourceType>
class ResourceRegistry
{
// Vector containing all currently loaded resources as shared pointers; array index is resource ID
std::vector<ResourcePtr<ResourceType>> resources_;
// Mapping of all loaded resources from name (e.g. file name) to resource ID
std::map<std::string, ResourceIDType> resource_name_map_;
public:
ResourceRegistry() = default;
// No copy or move operations
ResourceRegistry(const ResourceRegistry&) = delete;
ResourceRegistry& operator=(const ResourceRegistry&) = delete;
ResourceRegistry(ResourceRegistry&&) = delete;
ResourceRegistry& operator=(ResourceRegistry&&) = delete;
~ResourceRegistry() = default;
/**
* Return a reference to a shared pointer of the resource with the given ID.
*
* The reference is not guaranteed to be valid after adding new resources to the registry. Copy the
* reference into a new shared_ptr if you want to keep using it.
*
* Assumes that the resource ID is valid (debug assertions only).
*/
const ResourcePtr<ResourceType>& get_resource_by_id(const ResourceIDType resource_id) const
{
assert(resource_id < resources_.size());
assert(resources_[resource_id].use_count() > 0);
return resources_[resource_id];
}
/**
* Find the resource ID for a given resource name, or return `std::nullopt` if the resource was not found.
*/
std::optional<ResourceIDType> find_resource_id_by_name(const std::string& name) const
{
// Check if resource is already loaded
const auto search = resource_name_map_.find(name);
if (search != resource_name_map_.end()) {
// Return resource ID
return search->second;
}
return std::nullopt;
}
/**
* Add a new resource (without a name) to the registry and return its ID.
*/
ResourceIDType add_resource(ResourceType&& resource)
{
// Add resource to end of vector, moving the resource object into a shared_ptr
resources_.push_back(
std::make_shared<ResourceType>(std::move(resource))
);
// Return the index of the newly added resource
return static_cast<ResourceIDType>(resources_.size() - 1);
}
/**
* Add a new named resource to the registry, associate the name with it and return its ID.
*/
ResourceIDType add_resource(ResourceType&& resource, const std::string& name)
{
// Add resource
ResourceIDType resource_id = add_resource(std::move(resource));
// Associate name with resource ID for future access
resource_name_map_.emplace(name, resource_id);
return resource_id;
}
/**
* Load a resource by (file) name using the given resource loader and add it to the registry, unless the
* resource is already loaded.
* Return the resource ID (in both cases).
*/
template <IsResourceLoader<ResourceType> ResourceLoaderType>
ResourceIDType load_resource(const std::string& name, ResourceLoaderType& resource_loader)
{
// Check if resource is already loaded
auto resource_id = find_resource_id_by_name(name);
if (resource_id.has_value()) {
return resource_id.value();
}
// Load resource and add it to the registry
return add_resource(resource_loader.load_resource(name), name);
}
/**
* Load a resource if it's not loaded yet (like `load_resource()`), then return a reference to a shared
* pointer to the resource (like `get_resource_by_id()`).
*/
template <IsResourceLoader<ResourceType> ResourceLoaderType>
const ResourcePtr<ResourceType>& load_and_get_resource(
const std::string& name,
ResourceLoaderType& resource_loader
)
{
ResourceIDType resource_id = load_resource(name, resource_loader);
return get_resource_by_id(resource_id);
}
};
}

View file

@ -0,0 +1,12 @@
module;
export module rutile.core.resources.texture;
import std;
import wrappers.sdl;
export namespace rutile
{
using TextureID = unsigned int;
using Texture = sdl::Texture;
}

View file

@ -2,10 +2,11 @@ module;
#include <cassert> #include <cassert>
export module rutile.core.drawing.tile_set; export module rutile.core.resources.tile_set;
import std; import std;
import rutile.core.render_server; import rutile.core.common;
import rutile.core.resources.texture;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile
@ -20,8 +21,8 @@ export namespace rutile
class TileSet class TileSet
{ {
// Texture ID of tileset atlas texture // Shared pointer to the tileset atlas texture (managed by ResourceServer)
TextureID texture_id_; ResourcePtr<Texture> texture_ptr_;
// Size of each tile in pixels // Size of each tile in pixels
// TODO: Do we need this? // TODO: Do we need this?
@ -35,27 +36,23 @@ export namespace rutile
TileSet() = delete; TileSet() = delete;
explicit TileSet( explicit TileSet(
const TextureID texture_id, const ResourcePtr<Texture>& texture_ptr,
std::vector<TileDefinition> tile_definitions std::vector<TileDefinition> tile_definitions
) )
: texture_id_{texture_id}, : texture_ptr_{texture_ptr},
tile_definitions_{std::move(tile_definitions)} tile_definitions_{std::move(tile_definitions)}
{} {}
static TileSet create_from_texture( static TileSet create_from_texture(
RenderServer& render_server, const ResourcePtr<Texture>& texture_ptr,
const std::string& filename,
const int tile_size, const int tile_size,
const std::vector<sdl::Point>& tile_atlas_coords const std::vector<sdl::Point>& tile_atlas_coords
) )
{ {
const TextureID texture_id = render_server.load_texture(filename);
const sdl::Texture& texture = render_server.get_texture(texture_id);
assert(tile_size > 0); assert(tile_size > 0);
// TODO: These probably shouldn't be asserts... // TODO: These probably shouldn't be asserts...
assert(texture.get_width() % tile_size == 0); assert(texture_ptr->get_width() % tile_size == 0);
assert(texture.get_height() % tile_size == 0); assert(texture_ptr->get_height() % tile_size == 0);
std::vector<TileDefinition> tile_definitions; std::vector<TileDefinition> tile_definitions;
@ -71,17 +68,17 @@ export namespace rutile
}; };
// TODO: These probably shouldn't be asserts... // TODO: These probably shouldn't be asserts...
assert(tile.atlas_src_rect.x + tile.atlas_src_rect.w <= texture.get_width()); assert(tile.atlas_src_rect.x + tile.atlas_src_rect.w <= texture_ptr->get_width());
assert(tile.atlas_src_rect.y + tile.atlas_src_rect.h <= texture.get_height()); assert(tile.atlas_src_rect.y + tile.atlas_src_rect.h <= texture_ptr->get_height());
tile_definitions.push_back(tile); tile_definitions.push_back(tile);
} }
return TileSet(texture_id, tile_definitions); return TileSet(texture_ptr, tile_definitions);
} }
constexpr TextureID get_texture_id() const constexpr const Texture& get_texture() const
{ {
return texture_id_; return *texture_ptr_;
} }
constexpr const TileDefinition& get_tile_definition(const TileID tile_id) const constexpr const TileDefinition& get_tile_definition(const TileID tile_id) const

View file

@ -7,7 +7,6 @@ export module rutile.game.game;
import std; import std;
import rutile.core.drawing.sprite; import rutile.core.drawing.sprite;
import rutile.core.drawing.tile_map; import rutile.core.drawing.tile_map;
import rutile.core.drawing.tile_set;
import rutile.core.engine; import rutile.core.engine;
import rutile.core.render_server; import rutile.core.render_server;
import wrappers.rmlui.core; import wrappers.rmlui.core;
@ -24,12 +23,9 @@ export namespace rutile
// Reference to the engine // Reference to the engine
Engine& engine_; Engine& engine_;
// Sprites for testing // Sprites and stuff for testing
Sprite player_sprite_; Sprite player_sprite_;
std::vector<Sprite> sprites_; std::vector<Sprite> sprites_;
// Tile set and tile map (TODO: tile set should be moved to resource manager in engine)
TileSet tile_set_;
TileMap tile_map_; TileMap tile_map_;
// Private constructor // Private constructor
@ -37,30 +33,16 @@ export namespace rutile
: engine_(engine), : engine_(engine),
player_sprite_{ player_sprite_{
Sprite::create_from_texture( Sprite::create_from_texture(
engine_.get_render_server(), engine_.get_resource_server().load_texture("assets/sprites/neocat_64.png"),
"assets/sprites/neocat_64.png",
std::nullopt, std::nullopt,
sdl::FPoint{0, 0}, sdl::FPoint{0, 0},
sdl::FPoint{-32, -32} sdl::FPoint{-32, -32}
) )
}, },
tile_set_{ tile_map_{
TileSet::create_from_texture( engine_.get_resource_server().load_tile_set("assets/tilesets/terrain.png"),
engine_.get_render_server(), 32, 16, 12, {50, 50}
"assets/tilesets/terrain.png", }
32,
{
// Tile 0: No tile
{0, 0},
// Tile 1: Actual first tile in the texture
{0, 0},
{1, 0},
{2, 0},
{3, 0},
}
)
},
tile_map_(0, 32, 16, 12, {50, 50})
{ {
// Initialize UI // Initialize UI
const auto& ui_server = engine_.get_ui_server(); const auto& ui_server = engine_.get_ui_server();
@ -113,8 +95,7 @@ export namespace rutile
if (event.type == sdl::EventTypes::MouseButtonUp) { if (event.type == sdl::EventTypes::MouseButtonUp) {
sprites_.push_back( sprites_.push_back(
Sprite::create_from_texture( Sprite::create_from_texture(
engine_.get_render_server(), engine_.get_resource_server().load_texture("assets/sprites/neofox_64.png"),
"assets/sprites/neofox_64.png",
std::nullopt, std::nullopt,
sdl::FPoint{event.motion.x, event.motion.y}, sdl::FPoint{event.motion.x, event.motion.y},
sdl::FPoint{-32, -32} sdl::FPoint{-32, -32}
@ -138,7 +119,7 @@ export namespace rutile
render_server.start_frame(); render_server.start_frame();
// Render tilemap // Render tilemap
tile_map_.draw(render_server, tile_set_); tile_map_.draw(render_server);
// Render sprites // Render sprites
for (const Sprite& sprite : sprites_) { for (const Sprite& sprite : sprites_) {

View file

@ -56,7 +56,8 @@ export namespace sdl
*/ */
std::pair<int, int> get_size() const std::pair<int, int> get_size() const
{ {
int width, height; int width = 0;
int height = 0;
if (!SDL_GetWindowSize(get_raw(), &width, &height)) { if (!SDL_GetWindowSize(get_raw(), &width, &height)) {
throw SDLException("SDL_GetWindowSize"); throw SDLException("SDL_GetWindowSize");