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)
{
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
{
renderer_.clear();
@ -60,16 +68,16 @@ export namespace core
renderer_.present();
}
constexpr void render_texture(
void render_texture(
const TextureID texture_id,
const sdl::FRect* src_rect,
const sdl::FRect* dest_rect
) 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::FRect* src_rect,
const sdl::FRect* dest_rect

View File

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