From b770475741b7c33d57331f3139c55a3f237ad274 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 5 Nov 2024 16:03:48 +0100 Subject: create facade folder --- contributing.md | 1 + src/crepe/CMakeLists.txt | 11 +-- src/crepe/SDLApp.cpp | 71 ----------------- src/crepe/SDLApp.h | 26 ------- src/crepe/SDLContext.cpp | 157 -------------------------------------- src/crepe/SDLContext.h | 49 ------------ src/crepe/Sound.cpp | 60 --------------- src/crepe/Sound.h | 81 -------------------- src/crepe/SoundContext.cpp | 20 ----- src/crepe/SoundContext.h | 26 ------- src/crepe/api/AudioSource.cpp | 2 +- src/crepe/api/Texture.cpp | 2 +- src/crepe/facade/CMakeLists.txt | 14 ++++ src/crepe/facade/SDLApp.cpp | 71 +++++++++++++++++ src/crepe/facade/SDLApp.h | 26 +++++++ src/crepe/facade/SDLContext.cpp | 157 ++++++++++++++++++++++++++++++++++++++ src/crepe/facade/SDLContext.h | 48 ++++++++++++ src/crepe/facade/Sound.cpp | 60 +++++++++++++++ src/crepe/facade/Sound.h | 81 ++++++++++++++++++++ src/crepe/facade/SoundContext.cpp | 20 +++++ src/crepe/facade/SoundContext.h | 26 +++++++ src/crepe/system/RenderSystem.cpp | 2 +- src/example/asset_manager.cpp | 2 +- src/example/audio_internal.cpp | 2 +- src/example/particle.cpp | 2 +- 25 files changed, 512 insertions(+), 505 deletions(-) delete mode 100644 src/crepe/SDLApp.cpp delete mode 100644 src/crepe/SDLApp.h delete mode 100644 src/crepe/SDLContext.cpp delete mode 100644 src/crepe/SDLContext.h delete mode 100644 src/crepe/Sound.cpp delete mode 100644 src/crepe/Sound.h delete mode 100644 src/crepe/SoundContext.cpp delete mode 100644 src/crepe/SoundContext.h create mode 100644 src/crepe/facade/CMakeLists.txt create mode 100644 src/crepe/facade/SDLApp.cpp create mode 100644 src/crepe/facade/SDLApp.h create mode 100644 src/crepe/facade/SDLContext.cpp create mode 100644 src/crepe/facade/SDLContext.h create mode 100644 src/crepe/facade/Sound.cpp create mode 100644 src/crepe/facade/Sound.h create mode 100644 src/crepe/facade/SoundContext.cpp create mode 100644 src/crepe/facade/SoundContext.h diff --git a/contributing.md b/contributing.md index 35d777d..2fe46f7 100644 --- a/contributing.md +++ b/contributing.md @@ -403,6 +403,7 @@ that you can click on to open them. |`crepe/api/`|User-facing APIs| |`crepe/util/`|Standalone utilities and helper functions| |`crepe/system/`|(ECS) system classes| + |`crepe/facade/`|Library façades| - Do not (indirectly) include private *dependency* headers in API header files, as these are no longer accessible when the engine is installed - All code is implemented under the `crepe` namespace. diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 7f976db..8830e05 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,28 +1,21 @@ target_sources(crepe PUBLIC Asset.cpp - Sound.cpp - SoundContext.cpp Particle.cpp - SDLApp.cpp ComponentManager.cpp Component.cpp Collider.cpp - SDLContext.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES Asset.h - Sound.h - SoundContext.h - SDLContext.h ComponentManager.h ComponentManager.hpp Component.h Collider.h - SDLContext.h ) add_subdirectory(api) -add_subdirectory(util) +add_subdirectory(facade) add_subdirectory(system) +add_subdirectory(util) diff --git a/src/crepe/SDLApp.cpp b/src/crepe/SDLApp.cpp deleted file mode 100644 index c6ddeaa..0000000 --- a/src/crepe/SDLApp.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include - -#include "SDLApp.h" - -SDLApp::SDLApp(int window_width, int window_height) - : window_width(window_width), window_height(window_height), window(nullptr), - renderer(nullptr) {} - -// FIXME: why is there clean_up and ~SDLApp? -SDLApp::~SDLApp() { clean_up(); } - -bool SDLApp::initialize() { - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - // FIXME: throw exception - std::cerr << "SDL Initialization Error: " << SDL_GetError() - << std::endl; - return false; - } - - window = SDL_CreateWindow("Particle System", SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, window_width, - window_height, SDL_WINDOW_SHOWN); - if (!window) { - // FIXME: throw exception - std::cerr << "Window Creation Error: " << SDL_GetError() << std::endl; - return false; - } - - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - if (!renderer) { - // FIXME: throw exception - std::cerr << "Renderer Creation Error: " << SDL_GetError() << std::endl; - return false; - } - - return true; -} - -void SDLApp::handle_events(bool & running) { - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - running = false; - } - } -} - -void SDLApp::clear_screen() { - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderClear(renderer); -} - -void SDLApp::present_screen() { SDL_RenderPresent(renderer); } - -void SDLApp::draw_square(int x, int y, int size) { - SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - SDL_Rect rect = {x, y, size, size}; - SDL_RenderFillRect(renderer, &rect); -} - -SDL_Texture * square_texture = nullptr; // Load this with an image or create it - -void SDLApp::clean_up() { - if (renderer) { - SDL_DestroyRenderer(renderer); - } - if (window) { - SDL_DestroyWindow(window); - } - SDL_Quit(); -} diff --git a/src/crepe/SDLApp.h b/src/crepe/SDLApp.h deleted file mode 100644 index e67947b..0000000 --- a/src/crepe/SDLApp.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include "api/ParticleEmitter.h" - -class SDLApp { -public: - SDLApp(int window_width, int window_height); - ~SDLApp(); - - bool initialize(); - void handle_events(bool & running); - void clear_screen(); - void present_screen(); - void draw_square(int x, int y, int size); - void clean_up(); - void draw_particles(const std::vector & emitters); - void draw_multiple_squares(const std::vector & squares); - -private: - int window_width; - int window_height; - SDL_Window * window; - SDL_Renderer * renderer; -}; diff --git a/src/crepe/SDLContext.cpp b/src/crepe/SDLContext.cpp deleted file mode 100644 index e61faa3..0000000 --- a/src/crepe/SDLContext.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "api/Sprite.h" -#include "api/Texture.h" -#include "api/Transform.h" -#include "util/log.h" - -#include "SDLContext.h" - -using namespace crepe; - -SDLContext & SDLContext::get_instance() { - static SDLContext instance; - return instance; -} - -void SDLContext::handle_events(bool & running) { - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - running = false; - } - } -} - -SDLContext::~SDLContext() { - dbg_trace(); - - if (this->game_renderer != nullptr) - SDL_DestroyRenderer(this->game_renderer); - - if (this->game_window != nullptr) { - SDL_DestroyWindow(this->game_window); - } - - // TODO: how are we going to ensure that these are called from the same - // thread that SDL_Init() was called on? This has caused problems for me - // before. - IMG_Quit(); - SDL_Quit(); -} - -void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer); } - -SDLContext::SDLContext() { - dbg_trace(); - // FIXME: read window defaults from config manager - - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - // FIXME: throw exception - std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() - << std::endl; - return; - } - - this->game_window = SDL_CreateWindow( - "Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - 1920, 1080, SDL_WINDOW_SHOWN); - if (!this->game_window) { - // FIXME: throw exception - std::cerr << "Window could not be created! SDL_Error: " - << SDL_GetError() << std::endl; - } - - this->game_renderer - = SDL_CreateRenderer(this->game_window, -1, SDL_RENDERER_ACCELERATED); - if (!this->game_renderer) { - // FIXME: throw exception - std::cerr << "Renderer could not be created! SDL_Error: " - << SDL_GetError() << std::endl; - SDL_DestroyWindow(this->game_window); - return; - } - - int img_flags = IMG_INIT_PNG; - if (!(IMG_Init(img_flags) & img_flags)) { - // FIXME: throw exception - std::cout << "SDL_image could not initialize! SDL_image Error: " - << IMG_GetError() << std::endl; - } -} - -void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer); } - -void SDLContext::draw(const Sprite & sprite, const Transform & transform) { - - static SDL_RendererFlip render_flip - = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) - | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); - - int w, h; - SDL_QueryTexture(sprite.sprite_image->texture, NULL, NULL, &w, &h); - // needs maybe camera for position - SDL_Rect dstrect = { - .x = static_cast(transform.position.x), - .y = static_cast(transform.position.y), - .w = static_cast(w * transform.scale), - .h = static_cast(h * transform.scale), - }; - - double degrees = transform.rotation * 180 / M_PI; - SDL_RenderCopyEx(this->game_renderer, sprite.sprite_image->texture, NULL, - &dstrect, degrees, NULL, render_flip); -} - -/* -SDL_Texture * SDLContext::setTextureFromPath(const char * path, SDL_Rect & clip, - const int row, const int col) { - dbg_trace(); - - SDL_Surface * tmp = IMG_Load(path); - if (!tmp) { - std::cerr << "Error surface " << IMG_GetError << std::endl; - } - - clip. - w = tmp->w / col; - clip.h = tmp->h / row; - - SDL_Texture * CreatedTexture - = SDL_CreateTextureFromSurface(this->game_renderer, tmp); - - if (!CreatedTexture) { - std::cerr << "Error could not create texture " << IMG_GetError - << std::endl; - } - SDL_FreeSurface(tmp); - - return CreatedTexture; -} -*/ - -SDL_Texture * SDLContext::texture_from_path(const char * path) { - dbg_trace(); - - SDL_Surface * tmp = IMG_Load(path); - if (!tmp) { - std::cerr << "Error surface " << IMG_GetError << std::endl; - } - SDL_Texture * created_texture - = SDL_CreateTextureFromSurface(this->game_renderer, tmp); - - if (!created_texture) { - std::cerr << "Error could not create texture " << IMG_GetError - << std::endl; - } - SDL_FreeSurface(tmp); - - return created_texture; -} diff --git a/src/crepe/SDLContext.h b/src/crepe/SDLContext.h deleted file mode 100644 index 94fc549..0000000 --- a/src/crepe/SDLContext.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#include "api/Sprite.h" -#include "api/Transform.h" - -#include "system/RenderSystem.h" - -namespace crepe { - -class Texture; -class SDLContext { - -public: - // singleton - static SDLContext & get_instance(); - SDLContext(const SDLContext &) = delete; - SDLContext(SDLContext &&) = delete; - SDLContext & operator=(const SDLContext &) = delete; - SDLContext & operator=(SDLContext &&) = delete; - - //TODO decide events wouter? - -private: - void handle_events(bool & running); - -private: - SDLContext(); - virtual ~SDLContext(); - -private: - friend class Texture; - SDL_Texture * texture_from_path(const char *); - //SDL_Texture* setTextureFromPath(const char*, SDL_Rect& clip, const int row, const int col); - -private: - friend class RenderSystem; - void draw(const Sprite &, const Transform &); - void clear_screen(); - void present_screen(); - -private: - SDL_Window * game_window = nullptr; - SDL_Renderer * game_renderer = nullptr; -}; - -} // namespace crepe diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp deleted file mode 100644 index 64fa281..0000000 --- a/src/crepe/Sound.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "util/log.h" - -#include "Sound.h" -#include "SoundContext.h" - -using namespace crepe; - -Sound::Sound(std::unique_ptr res) { - dbg_trace(); - this->load(std::move(res)); -} - -Sound::Sound(const char * src) { - dbg_trace(); - this->load(std::make_unique(src)); -} - -void Sound::load(std::unique_ptr res) { - this->sample.load(res->canonical()); -} - -void Sound::play() { - SoundContext & ctx = SoundContext::get_instance(); - if (ctx.engine.getPause(this->handle)) { - // resume if paused - ctx.engine.setPause(this->handle, false); - } else { - // or start new sound - this->handle = ctx.engine.play(this->sample, this->volume); - ctx.engine.setLooping(this->handle, this->looping); - } -} - -void Sound::pause() { - SoundContext & ctx = SoundContext::get_instance(); - if (ctx.engine.getPause(this->handle)) return; - ctx.engine.setPause(this->handle, true); -} - -void Sound::rewind() { - SoundContext & ctx = SoundContext::get_instance(); - if (!ctx.engine.isValidVoiceHandle(this->handle)) return; - ctx.engine.seek(this->handle, 0); -} - -void Sound::set_volume(float volume) { - this->volume = volume; - - SoundContext & ctx = SoundContext::get_instance(); - if (!ctx.engine.isValidVoiceHandle(this->handle)) return; - ctx.engine.setVolume(this->handle, this->volume); -} - -void Sound::set_looping(bool looping) { - this->looping = looping; - - SoundContext & ctx = SoundContext::get_instance(); - if (!ctx.engine.isValidVoiceHandle(this->handle)) return; - ctx.engine.setLooping(this->handle, this->looping); -} diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h deleted file mode 100644 index 917b57e..0000000 --- a/src/crepe/Sound.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Asset.h" - -namespace crepe { - -class Sound { -public: - /** - * \brief Pause this sample - * - * Pauses this sound if it is playing, or does nothing if it is already - * paused. The playhead position is saved, such that calling \c play() after - * this function makes the sound resume. - */ - void pause(); - /** - * \brief Play this sample - * - * Resume playback if this sound is paused, or start from the beginning of - * the sample. - * - * \note This class only saves a reference to the most recent 'voice' of this - * sound. Calling \c play() while the sound is already playing causes - * multiple instances of the sample to play simultaniously. The sample - * started last is the one that is controlled afterwards. - */ - void play(); - /** - * \brief Reset playhead position - * - * Resets the playhead position so that calling \c play() after this function - * makes it play from the start of the sample. If the sound is not paused - * before calling this function, this function will stop playback. - */ - void rewind(); - /** - * \brief Set playback volume / gain - * - * \param volume Volume (0 = muted, 1 = full volume) - */ - void set_volume(float volume); - /** - * \brief Get playback volume / gain - * - * \return Volume - */ - float get_volume() const { return this->volume; } - /** - * \brief Set looping behavior for this sample - * - * \param looping Looping behavior (false = one-shot, true = loop) - */ - void set_looping(bool looping); - /** - * \brief Get looping behavior - * - * \return true if looping, false if one-shot - */ - bool get_looping() const { return this->looping; } - -public: - Sound(const char * src); - Sound(std::unique_ptr res); - -private: - void load(std::unique_ptr res); - -private: - SoLoud::Wav sample; - SoLoud::handle handle; - - float volume = 1.0f; - bool looping = false; -}; - -} // namespace crepe diff --git a/src/crepe/SoundContext.cpp b/src/crepe/SoundContext.cpp deleted file mode 100644 index 72047d2..0000000 --- a/src/crepe/SoundContext.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "util/log.h" - -#include "SoundContext.h" - -using namespace crepe; - -SoundContext & SoundContext::get_instance() { - static SoundContext instance; - return instance; -} - -SoundContext::SoundContext() { - dbg_trace(); - engine.init(); -} - -SoundContext::~SoundContext() { - dbg_trace(); - engine.deinit(); -} diff --git a/src/crepe/SoundContext.h b/src/crepe/SoundContext.h deleted file mode 100644 index d3123d2..0000000 --- a/src/crepe/SoundContext.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include "Sound.h" - -namespace crepe { - -class SoundContext { -private: - SoundContext(); - virtual ~SoundContext(); - - // singleton - static SoundContext & get_instance(); - SoundContext(const SoundContext &) = delete; - SoundContext(SoundContext &&) = delete; - SoundContext & operator=(const SoundContext &) = delete; - SoundContext & operator=(SoundContext &&) = delete; - -private: - SoLoud::Soloud engine; - friend class Sound; -}; - -} // namespace crepe diff --git a/src/crepe/api/AudioSource.cpp b/src/crepe/api/AudioSource.cpp index 2bacc75..63fd0d7 100644 --- a/src/crepe/api/AudioSource.cpp +++ b/src/crepe/api/AudioSource.cpp @@ -1,6 +1,6 @@ #include -#include "../Sound.h" +#include "../facade/Sound.h" #include "AudioSource.h" diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index b5001a6..8fc5c13 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -1,6 +1,6 @@ #include -#include "../SDLContext.h" +#include "../facade/SDLContext.h" #include "../util/log.h" #include "Asset.h" diff --git a/src/crepe/facade/CMakeLists.txt b/src/crepe/facade/CMakeLists.txt new file mode 100644 index 0000000..dbddcc6 --- /dev/null +++ b/src/crepe/facade/CMakeLists.txt @@ -0,0 +1,14 @@ +target_sources(crepe PUBLIC + Sound.cpp + SoundContext.cpp + SDLApp.cpp + SDLContext.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + Sound.h + SoundContext.h + SDLContext.h + SDLContext.h +) + diff --git a/src/crepe/facade/SDLApp.cpp b/src/crepe/facade/SDLApp.cpp new file mode 100644 index 0000000..c6ddeaa --- /dev/null +++ b/src/crepe/facade/SDLApp.cpp @@ -0,0 +1,71 @@ +#include + +#include "SDLApp.h" + +SDLApp::SDLApp(int window_width, int window_height) + : window_width(window_width), window_height(window_height), window(nullptr), + renderer(nullptr) {} + +// FIXME: why is there clean_up and ~SDLApp? +SDLApp::~SDLApp() { clean_up(); } + +bool SDLApp::initialize() { + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + // FIXME: throw exception + std::cerr << "SDL Initialization Error: " << SDL_GetError() + << std::endl; + return false; + } + + window = SDL_CreateWindow("Particle System", SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, window_width, + window_height, SDL_WINDOW_SHOWN); + if (!window) { + // FIXME: throw exception + std::cerr << "Window Creation Error: " << SDL_GetError() << std::endl; + return false; + } + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if (!renderer) { + // FIXME: throw exception + std::cerr << "Renderer Creation Error: " << SDL_GetError() << std::endl; + return false; + } + + return true; +} + +void SDLApp::handle_events(bool & running) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + running = false; + } + } +} + +void SDLApp::clear_screen() { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); +} + +void SDLApp::present_screen() { SDL_RenderPresent(renderer); } + +void SDLApp::draw_square(int x, int y, int size) { + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDL_Rect rect = {x, y, size, size}; + SDL_RenderFillRect(renderer, &rect); +} + +SDL_Texture * square_texture = nullptr; // Load this with an image or create it + +void SDLApp::clean_up() { + if (renderer) { + SDL_DestroyRenderer(renderer); + } + if (window) { + SDL_DestroyWindow(window); + } + SDL_Quit(); +} diff --git a/src/crepe/facade/SDLApp.h b/src/crepe/facade/SDLApp.h new file mode 100644 index 0000000..6d8f3f4 --- /dev/null +++ b/src/crepe/facade/SDLApp.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "../api/ParticleEmitter.h" + +class SDLApp { +public: + SDLApp(int window_width, int window_height); + ~SDLApp(); + + bool initialize(); + void handle_events(bool & running); + void clear_screen(); + void present_screen(); + void draw_square(int x, int y, int size); + void clean_up(); + void draw_particles(const std::vector & emitters); + void draw_multiple_squares(const std::vector & squares); + +private: + int window_width; + int window_height; + SDL_Window * window; + SDL_Renderer * renderer; +}; diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp new file mode 100644 index 0000000..8da93e9 --- /dev/null +++ b/src/crepe/facade/SDLContext.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../api/Sprite.h" +#include "../api/Texture.h" +#include "../api/Transform.h" +#include "../util/log.h" + +#include "SDLContext.h" + +using namespace crepe; + +SDLContext & SDLContext::get_instance() { + static SDLContext instance; + return instance; +} + +void SDLContext::handle_events(bool & running) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + running = false; + } + } +} + +SDLContext::~SDLContext() { + dbg_trace(); + + if (this->game_renderer != nullptr) + SDL_DestroyRenderer(this->game_renderer); + + if (this->game_window != nullptr) { + SDL_DestroyWindow(this->game_window); + } + + // TODO: how are we going to ensure that these are called from the same + // thread that SDL_Init() was called on? This has caused problems for me + // before. + IMG_Quit(); + SDL_Quit(); +} + +void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer); } + +SDLContext::SDLContext() { + dbg_trace(); + // FIXME: read window defaults from config manager + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + // FIXME: throw exception + std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() + << std::endl; + return; + } + + this->game_window = SDL_CreateWindow( + "Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + 1920, 1080, SDL_WINDOW_SHOWN); + if (!this->game_window) { + // FIXME: throw exception + std::cerr << "Window could not be created! SDL_Error: " + << SDL_GetError() << std::endl; + } + + this->game_renderer + = SDL_CreateRenderer(this->game_window, -1, SDL_RENDERER_ACCELERATED); + if (!this->game_renderer) { + // FIXME: throw exception + std::cerr << "Renderer could not be created! SDL_Error: " + << SDL_GetError() << std::endl; + SDL_DestroyWindow(this->game_window); + return; + } + + int img_flags = IMG_INIT_PNG; + if (!(IMG_Init(img_flags) & img_flags)) { + // FIXME: throw exception + std::cout << "SDL_image could not initialize! SDL_image Error: " + << IMG_GetError() << std::endl; + } +} + +void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer); } + +void SDLContext::draw(const Sprite & sprite, const Transform & transform) { + + static SDL_RendererFlip render_flip + = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) + | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); + + int w, h; + SDL_QueryTexture(sprite.sprite_image->texture, NULL, NULL, &w, &h); + // needs maybe camera for position + SDL_Rect dstrect = { + .x = static_cast(transform.position.x), + .y = static_cast(transform.position.y), + .w = static_cast(w * transform.scale), + .h = static_cast(h * transform.scale), + }; + + double degrees = transform.rotation * 180 / M_PI; + SDL_RenderCopyEx(this->game_renderer, sprite.sprite_image->texture, NULL, + &dstrect, degrees, NULL, render_flip); +} + +/* +SDL_Texture * SDLContext::setTextureFromPath(const char * path, SDL_Rect & clip, + const int row, const int col) { + dbg_trace(); + + SDL_Surface * tmp = IMG_Load(path); + if (!tmp) { + std::cerr << "Error surface " << IMG_GetError << std::endl; + } + + clip. + w = tmp->w / col; + clip.h = tmp->h / row; + + SDL_Texture * CreatedTexture + = SDL_CreateTextureFromSurface(this->game_renderer, tmp); + + if (!CreatedTexture) { + std::cerr << "Error could not create texture " << IMG_GetError + << std::endl; + } + SDL_FreeSurface(tmp); + + return CreatedTexture; +} +*/ + +SDL_Texture * SDLContext::texture_from_path(const char * path) { + dbg_trace(); + + SDL_Surface * tmp = IMG_Load(path); + if (!tmp) { + std::cerr << "Error surface " << IMG_GetError << std::endl; + } + SDL_Texture * created_texture + = SDL_CreateTextureFromSurface(this->game_renderer, tmp); + + if (!created_texture) { + std::cerr << "Error could not create texture " << IMG_GetError + << std::endl; + } + SDL_FreeSurface(tmp); + + return created_texture; +} diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h new file mode 100644 index 0000000..f1ba8a6 --- /dev/null +++ b/src/crepe/facade/SDLContext.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#include "../api/Sprite.h" +#include "../api/Transform.h" +#include "../system/RenderSystem.h" + +namespace crepe { + +class Texture; +class SDLContext { + +public: + // singleton + static SDLContext & get_instance(); + SDLContext(const SDLContext &) = delete; + SDLContext(SDLContext &&) = delete; + SDLContext & operator=(const SDLContext &) = delete; + SDLContext & operator=(SDLContext &&) = delete; + + //TODO decide events wouter? + +private: + void handle_events(bool & running); + +private: + SDLContext(); + virtual ~SDLContext(); + +private: + friend class Texture; + SDL_Texture * texture_from_path(const char *); + //SDL_Texture* setTextureFromPath(const char*, SDL_Rect& clip, const int row, const int col); + +private: + friend class RenderSystem; + void draw(const Sprite &, const Transform &); + void clear_screen(); + void present_screen(); + +private: + SDL_Window * game_window = nullptr; + SDL_Renderer * game_renderer = nullptr; +}; + +} // namespace crepe diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp new file mode 100644 index 0000000..648ec81 --- /dev/null +++ b/src/crepe/facade/Sound.cpp @@ -0,0 +1,60 @@ +#include "../util/log.h" + +#include "Sound.h" +#include "SoundContext.h" + +using namespace crepe; + +Sound::Sound(std::unique_ptr res) { + dbg_trace(); + this->load(std::move(res)); +} + +Sound::Sound(const char * src) { + dbg_trace(); + this->load(std::make_unique(src)); +} + +void Sound::load(std::unique_ptr res) { + this->sample.load(res->canonical()); +} + +void Sound::play() { + SoundContext & ctx = SoundContext::get_instance(); + if (ctx.engine.getPause(this->handle)) { + // resume if paused + ctx.engine.setPause(this->handle, false); + } else { + // or start new sound + this->handle = ctx.engine.play(this->sample, this->volume); + ctx.engine.setLooping(this->handle, this->looping); + } +} + +void Sound::pause() { + SoundContext & ctx = SoundContext::get_instance(); + if (ctx.engine.getPause(this->handle)) return; + ctx.engine.setPause(this->handle, true); +} + +void Sound::rewind() { + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.seek(this->handle, 0); +} + +void Sound::set_volume(float volume) { + this->volume = volume; + + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.setVolume(this->handle, this->volume); +} + +void Sound::set_looping(bool looping) { + this->looping = looping; + + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.setLooping(this->handle, this->looping); +} diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h new file mode 100644 index 0000000..183bd7c --- /dev/null +++ b/src/crepe/facade/Sound.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include + +#include "../Asset.h" + +namespace crepe { + +class Sound { +public: + /** + * \brief Pause this sample + * + * Pauses this sound if it is playing, or does nothing if it is already + * paused. The playhead position is saved, such that calling \c play() after + * this function makes the sound resume. + */ + void pause(); + /** + * \brief Play this sample + * + * Resume playback if this sound is paused, or start from the beginning of + * the sample. + * + * \note This class only saves a reference to the most recent 'voice' of this + * sound. Calling \c play() while the sound is already playing causes + * multiple instances of the sample to play simultaniously. The sample + * started last is the one that is controlled afterwards. + */ + void play(); + /** + * \brief Reset playhead position + * + * Resets the playhead position so that calling \c play() after this function + * makes it play from the start of the sample. If the sound is not paused + * before calling this function, this function will stop playback. + */ + void rewind(); + /** + * \brief Set playback volume / gain + * + * \param volume Volume (0 = muted, 1 = full volume) + */ + void set_volume(float volume); + /** + * \brief Get playback volume / gain + * + * \return Volume + */ + float get_volume() const { return this->volume; } + /** + * \brief Set looping behavior for this sample + * + * \param looping Looping behavior (false = one-shot, true = loop) + */ + void set_looping(bool looping); + /** + * \brief Get looping behavior + * + * \return true if looping, false if one-shot + */ + bool get_looping() const { return this->looping; } + +public: + Sound(const char * src); + Sound(std::unique_ptr res); + +private: + void load(std::unique_ptr res); + +private: + SoLoud::Wav sample; + SoLoud::handle handle; + + float volume = 1.0f; + bool looping = false; +}; + +} // namespace crepe diff --git a/src/crepe/facade/SoundContext.cpp b/src/crepe/facade/SoundContext.cpp new file mode 100644 index 0000000..5e5a3a9 --- /dev/null +++ b/src/crepe/facade/SoundContext.cpp @@ -0,0 +1,20 @@ +#include "../util/log.h" + +#include "SoundContext.h" + +using namespace crepe; + +SoundContext & SoundContext::get_instance() { + static SoundContext instance; + return instance; +} + +SoundContext::SoundContext() { + dbg_trace(); + engine.init(); +} + +SoundContext::~SoundContext() { + dbg_trace(); + engine.deinit(); +} diff --git a/src/crepe/facade/SoundContext.h b/src/crepe/facade/SoundContext.h new file mode 100644 index 0000000..d3123d2 --- /dev/null +++ b/src/crepe/facade/SoundContext.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "Sound.h" + +namespace crepe { + +class SoundContext { +private: + SoundContext(); + virtual ~SoundContext(); + + // singleton + static SoundContext & get_instance(); + SoundContext(const SoundContext &) = delete; + SoundContext(SoundContext &&) = delete; + SoundContext & operator=(const SoundContext &) = delete; + SoundContext & operator=(SoundContext &&) = delete; + +private: + SoLoud::Soloud engine; + friend class Sound; +}; + +} // namespace crepe diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index ee3cdf2..96c94e9 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -2,7 +2,7 @@ #include #include "../ComponentManager.h" -#include "../SDLContext.h" +#include "../facade/SDLContext.h" #include "../api/Sprite.h" #include "../api/Transform.h" #include "../util/log.h" diff --git a/src/example/asset_manager.cpp b/src/example/asset_manager.cpp index f0d4575..ba18b62 100644 --- a/src/example/asset_manager.cpp +++ b/src/example/asset_manager.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/example/audio_internal.cpp b/src/example/audio_internal.cpp index 7586441..0b36daa 100644 --- a/src/example/audio_internal.cpp +++ b/src/example/audio_internal.cpp @@ -3,7 +3,7 @@ * Standalone example for usage of the internal \c Sound class. */ -#include +#include #include #include diff --git a/src/example/particle.cpp b/src/example/particle.cpp index 38cff25..83b1e8a 100644 --- a/src/example/particle.cpp +++ b/src/example/particle.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3