Implement Sprite class

This commit is contained in:
Lexi / Zoe 2025-11-30 00:37:44 +01:00
parent d4c91450d9
commit bb9d108102
Signed by: binaryDiv
GPG Key ID: F8D4956E224DA232
7 changed files with 132 additions and 56 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,84 @@
module;
#include <cassert>
#include <optional>
#include <string>
#include <SDL3/SDL.h>
export module core.drawing.sprite;
import core.render_server;
import wrappers.sdl;
export namespace core
{
class Sprite
{
// Texture ID (managed by TextureManager in RenderServer)
TextureID texture_id_;
// Texture source boundaries: which part of the texture to render
sdl::FRect texture_boundaries_;
// Texture offset: static offset that is added to the render position (BEFORE scale is applied)
sdl::FPoint texture_offset_{0, 0};
// Texture scale: factors applied to width/height (AFTER offset is applied)
// TODO: Proper vector class?
sdl::FPoint texture_scale_{1, 1};
// Sprite position: where to render the sprite (world coordinates)
sdl::FPoint position_{0, 0};
public:
explicit Sprite(
const TextureID texture_id,
const sdl::FRect texture_boundaries,
const sdl::FPoint position,
const sdl::FPoint texture_offset = {0, 0},
const sdl::FPoint texture_scale = {1, 1}
)
: texture_id_{texture_id},
texture_boundaries_{texture_boundaries},
texture_offset_{texture_offset},
texture_scale_{texture_scale},
position_{position}
{
assert(texture_boundaries_.w > 0 && texture_boundaries_.h > 0);
}
static Sprite create_with_texture(
RenderServer& render_server,
const std::string& filename,
std::optional<sdl::FRect> texture_boundaries,
auto... args
)
{
const TextureID texture_id = render_server.load_texture(filename);
if (!texture_boundaries.has_value()) {
const sdl::Texture& texture = render_server.get_texture(texture_id);
texture_boundaries = texture.get_boundaries();
}
return Sprite(texture_id, texture_boundaries.value(), args...);
}
void set_position(const sdl::FPoint new_position)
{
position_ = new_position;
}
void draw(const RenderServer& render_server) const
{
const sdl::FRect dest_rect{
position_.x + (texture_scale_.x * texture_offset_.x),
position_.y + (texture_scale_.y * texture_offset_.y),
texture_scale_.x * texture_boundaries_.w,
texture_scale_.y * texture_boundaries_.h,
};
render_server.render_texture(texture_id_, &texture_boundaries_, &dest_rect);
}
};
}

View File

@ -43,13 +43,21 @@ export namespace core
} }
/** /**
* Loads a texture from a file (if not loaded yet) and returns its texture ID. * Load a texture from a file (if not loaded yet) and return its texture ID.
*/ */
constexpr TextureID load_texture(const std::string& filename) constexpr TextureID load_texture(const std::string& filename)
{ {
return texture_manager_.load_resource_by_name(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();
@ -60,16 +68,16 @@ export namespace core
renderer_.present(); renderer_.present();
} }
constexpr void render_texture( void render_texture(
const TextureID texture_id, const TextureID texture_id,
const sdl::FRect* src_rect, const sdl::FRect* src_rect,
const sdl::FRect* dest_rect const sdl::FRect* dest_rect
) const ) const
{ {
render_texture(texture_manager_.get_resource(texture_id), src_rect, dest_rect); render_texture(get_texture(texture_id), src_rect, dest_rect);
} }
void render_texture( constexpr void render_texture(
const sdl::Texture& texture, const sdl::Texture& texture,
const sdl::FRect* src_rect, const sdl::FRect* src_rect,
const sdl::FRect* dest_rect const sdl::FRect* dest_rect

View File

@ -2,14 +2,15 @@ module;
#include <cassert> #include <cassert>
#include <memory> #include <memory>
#include <optional>
#include <vector> #include <vector>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
export module game.game; export module game.game;
import core.drawing.sprite;
import core.engine; import core.engine;
import core.render_server; import core.render_server;
import game.sprite;
import wrappers.sdl; import wrappers.sdl;
import wrappers.sdl_image; import wrappers.sdl_image;
@ -24,15 +25,20 @@ export namespace game
core::Engine& engine_; core::Engine& engine_;
// Sprites for testing // Sprites for testing
Sprite player_sprite_; core::Sprite player_sprite_;
std::vector<Sprite> sprites_; std::vector<core::Sprite> sprites_;
// Private constructor // Private constructor
explicit Game(core::Engine& engine) explicit Game(core::Engine& engine)
: engine_(engine), : engine_(engine),
player_sprite_{ player_sprite_{
engine_.get_render_server().load_texture("assets/neocat.png"), core::Sprite::create_with_texture(
sdl::FRect{0, 0, 100, 100} engine_.get_render_server(),
"assets/sprites/neocat_64.png",
std::nullopt,
sdl::FPoint{0, 0},
sdl::FPoint{-32, -32}
)
} }
{} {}
@ -63,21 +69,19 @@ export namespace game
bool handle_event(const sdl::Event* event) bool handle_event(const sdl::Event* event)
{ {
if (event->type == sdl::EventType::MouseMotion) { if (event->type == sdl::EventType::MouseMotion) {
player_sprite_.move( player_sprite_.set_position({event->motion.x, event->motion.y});
event->motion.x - 50,
event->motion.y - 50
);
return true; return true;
} }
if (event->type == sdl::EventType::MouseButtonUp) { if (event->type == sdl::EventType::MouseButtonUp) {
sprites_.emplace_back( sprites_.push_back(
engine_.get_render_server().load_texture("assets/neofox.png"), core::Sprite::create_with_texture(
sdl::FRect{ engine_.get_render_server(),
event->motion.x - 50, "assets/sprites/neofox_64.png",
event->motion.y - 50, std::nullopt,
100, 100 sdl::FPoint{event->motion.x, event->motion.y},
} sdl::FPoint{-32, -32}
)
); );
return true; return true;
} }
@ -94,7 +98,7 @@ export namespace game
const auto& render_server = engine_.get_render_server(); const auto& render_server = engine_.get_render_server();
render_server.start_frame(); render_server.start_frame();
for (const Sprite& sprite : sprites_) { for (const core::Sprite& sprite : sprites_) {
sprite.draw(render_server); sprite.draw(render_server);
} }
player_sprite_.draw(render_server); player_sprite_.draw(render_server);

View File

@ -1,35 +0,0 @@
module;
#include <SDL3/SDL.h>
export module game.sprite;
import core.render_server;
import wrappers.sdl;
// TODO: Move this to a different namespace (core, drawing, ...?)
export namespace game
{
class Sprite
{
core::TextureID texture_id_;
sdl::FRect dest_rect_{0, 0, 0, 0};
public:
explicit Sprite(const core::TextureID texture_id, const sdl::FRect dest_rect)
: texture_id_{texture_id},
dest_rect_{dest_rect}
{}
void move(const float x, const float y)
{
dest_rect_.x = x;
dest_rect_.y = y;
}
void draw(const core::RenderServer& render_server) const
{
render_server.render_texture(texture_id_, nullptr, &dest_rect_);
}
};
}

View File

@ -35,6 +35,21 @@ export namespace sdl
assert(raw_texture_); assert(raw_texture_);
return raw_texture_.get(); return raw_texture_.get();
} }
constexpr int get_width() const
{
return raw_texture_->w;
}
constexpr int get_height() const
{
return raw_texture_->h;
}
constexpr FRect get_boundaries() const
{
return {0, 0, static_cast<float>(raw_texture_->w), static_cast<float>(raw_texture_->h)};
}
}; };
/** /**