From 0743e6dc626a273845ccbaedeb9d596fad034394 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Wed, 22 Oct 2025 17:04:43 +0200 Subject: [PATCH] Add simple boilerplace SDL code --- assets/neocat.png | Bin 0 -> 14387 bytes src/main.cpp | 28 ++++++++++++-- src/sdl_app.cppm | 95 ++++++++++++++++++++++++++++++++++++++++++++++ src/sprite.cppm | 81 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 assets/neocat.png create mode 100644 src/sdl_app.cppm create mode 100644 src/sprite.cppm diff --git a/assets/neocat.png b/assets/neocat.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa76179430f4cceb291f08c70bfa7bfe56757ed GIT binary patch literal 14387 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�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 literal 0 HcmV?d00001 diff --git a/src/main.cpp b/src/main.cpp index 283ffd6..cdfe69e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,27 @@ -#include +import sdl_app; -int main() { - std::cout << "Meow" << std::endl; +#define SDL_MAIN_USE_CALLBACKS +#include + +SDL_AppResult SDL_AppInit(void** appstate, int /*argc*/, char** /*argv*/) +{ + *appstate = new AppState; + return sdl_app_init(static_cast(*appstate)); +} + +SDL_AppResult SDL_AppIterate(void* appstate) +{ + return sdl_app_iterate(static_cast(appstate)); +} + +SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) +{ + return sdl_app_event(static_cast(appstate), event); +} + +void SDL_AppQuit(void* appstate, SDL_AppResult /*result*/) +{ + const auto* game_app_state = static_cast(appstate); + sdl_app_shutdown(game_app_state); + delete game_app_state; } diff --git a/src/sdl_app.cppm b/src/sdl_app.cppm new file mode 100644 index 0000000..7e14111 --- /dev/null +++ b/src/sdl_app.cppm @@ -0,0 +1,95 @@ +module; + +#include +#include +#include + +export module sdl_app; + +import sprite; + +export { + struct AppState + { + SDL_Window* window = nullptr; + SDL_Renderer* renderer = nullptr; + Sprite* sprite = nullptr; + }; + + SDL_AppResult sdl_panic( + const std::string& error_prefix, + SDL_Window* window = nullptr, + SDL_Renderer* renderer = nullptr + ) + { + std::cerr << error_prefix << ": " << SDL_GetError() << '\n'; + + if (renderer != nullptr) { + SDL_DestroyRenderer(renderer); + } + if (window != nullptr) { + SDL_DestroyWindow(window); + } + + SDL_Quit(); + return SDL_APP_FAILURE; + } + + SDL_AppResult sdl_app_init(AppState* app_state) + { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { + return sdl_panic("SDL_Init error"); + } + + app_state->window = SDL_CreateWindow("BuildSystemTest", 640, 480, 0); + if (app_state->window == nullptr) { + return sdl_panic("SDL_CreateWindow error"); + } + + app_state->renderer = SDL_CreateRenderer(app_state->window, nullptr); + if (app_state->renderer == nullptr) { + return sdl_panic("SDL_CreateRenderer error", app_state->window); + } + + try { + app_state->sprite = new Sprite(app_state->renderer, "assets/neocat.png", 100, 100); + } + catch (const std::runtime_error& e) { + return sdl_panic(e.what(), app_state->window, app_state->renderer); + } + + return SDL_APP_CONTINUE; + } + + SDL_AppResult sdl_app_event(const AppState* app_state, const SDL_Event* event) + { + if (event->type == SDL_EVENT_QUIT) { + return SDL_APP_SUCCESS; + } + + if (event->type == SDL_EVENT_MOUSE_MOTION) { + app_state->sprite->move( + event->motion.x - 50, + event->motion.y - 50 + ); + } + + return SDL_APP_CONTINUE; + } + + SDL_AppResult sdl_app_iterate(const AppState* app_state) + { + SDL_RenderClear(app_state->renderer); + app_state->sprite->render(app_state->renderer); + SDL_RenderPresent(app_state->renderer); + + return SDL_APP_CONTINUE; + } + + void sdl_app_shutdown(const AppState* app_state) + { + delete app_state->sprite; + SDL_DestroyRenderer(app_state->renderer); + SDL_DestroyWindow(app_state->window); + } +} diff --git a/src/sprite.cppm b/src/sprite.cppm new file mode 100644 index 0000000..3318180 --- /dev/null +++ b/src/sprite.cppm @@ -0,0 +1,81 @@ +module; + +#include +#include +#include +#include + +export module sprite; + +export class Sprite +{ + SDL_Texture* sdl_texture; + SDL_FRect dest_rect{0, 0, 0, 0}; + + public: + explicit Sprite( + SDL_Renderer* renderer, + const std::string& filename, + const int width, + const int height + ) + { + SDL_Surface* texture_surface = IMG_Load(filename.c_str()); + if (texture_surface == nullptr) { + throw std::runtime_error("IMG_Load error"); + } + + sdl_texture = SDL_CreateTextureFromSurface(renderer, texture_surface); + SDL_DestroySurface(texture_surface); + + if (sdl_texture == nullptr) { + throw std::runtime_error("SDL_CreateTextureFromSurface error"); + } + + dest_rect.w = static_cast(width); + dest_rect.h = static_cast(height); + } + + // Don't allow copy operations + Sprite(const Sprite&) = delete; + Sprite& operator=(const Sprite&) = delete; + + // Move constructor + Sprite(Sprite&& other) noexcept + : sdl_texture(other.sdl_texture), + dest_rect(other.dest_rect) + { + other.sdl_texture = nullptr; + } + + // Move assignment + Sprite& operator=(Sprite&& other) noexcept + { + // Move inner resources from other + sdl_texture = other.sdl_texture; + dest_rect = other.dest_rect; + + // Reset other to make it safe for deletion + other.sdl_texture = nullptr; + + return *this; + } + + ~Sprite() + { + if (sdl_texture != nullptr) { + SDL_DestroyTexture(sdl_texture); + } + } + + void move(const float x, const float y) + { + dest_rect.x = x; + dest_rect.y = y; + } + + void render(SDL_Renderer* renderer) const + { + SDL_RenderTexture(renderer, sdl_texture, nullptr, &dest_rect); + } +};