diff options
Diffstat (limited to 'src/crepe/facade')
-rw-r--r-- | src/crepe/facade/SDLContext.cpp | 130 | ||||
-rw-r--r-- | src/crepe/facade/SDLContext.h | 73 | ||||
-rw-r--r-- | src/crepe/facade/Sound.h | 2 |
3 files changed, 135 insertions, 70 deletions
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index ad9f1f0..4cc2206 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -11,19 +11,17 @@ #include <cstddef> #include <cstdint> #include <functional> -#include <iostream> #include <memory> #include <stdexcept> #include "../api/Camera.h" +#include "../api/Color.h" #include "../api/Config.h" #include "../api/Sprite.h" #include "../api/Texture.h" -#include "../manager/EventManager.h" #include "../util/Log.h" #include "SDLContext.h" -#include "api/Color.h" #include "types.h" using namespace crepe; @@ -215,11 +213,13 @@ MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) { return MOUSE_BUTTON_LOOKUP_TABLE[sdl_button]; } -void SDLContext::clear_screen() { +void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } +void SDLContext::present_screen() { SDL_SetRenderDrawColor(this->game_renderer.get(), 0, 0, 0, 255); - SDL_RenderClear(this->game_renderer.get()); + SDL_RenderFillRectF(this->game_renderer.get(), &black_bars[0]); + SDL_RenderFillRectF(this->game_renderer.get(), &black_bars[1]); + SDL_RenderPresent(this->game_renderer.get()); } -void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { return SDL_Rect{ @@ -229,40 +229,62 @@ SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { .h = sprite.mask.h, }; } -SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const vec2 & pos, const Camera & cam, - const vec2 & cam_pos, const double & img_scale) const { - int width = sprite.height * sprite.aspect_ratio; - int height = sprite.height; +SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const { - width *= img_scale * cam.zoom; - height *= img_scale * cam.zoom; + const Sprite::Data & data = ctx.sprite.data; - return SDL_Rect{ - .x = static_cast<int>((pos.x - cam_pos.x + (cam.viewport_size.x / 2) - width / 2)), - .y = static_cast<int>((pos.y - cam_pos.y + (cam.viewport_size.y / 2) - height / 2)), - .w = width, - .h = height, + vec2 size; + if (data.size.x == 0 && data.size.y != 0) { + size.x = data.size.y * ctx.sprite.aspect_ratio; + } + if (data.size.y == 0 && data.size.x != 0) { + size.y = data.size.x / ctx.sprite.aspect_ratio; + } + + const CameraValues & cam = ctx.cam; + + size *= cam.render_scale * ctx.img_scale * data.scale_offset; + + vec2 screen_pos + = (ctx.pos + data.position_offset - cam.cam_pos + (cam.zoomed_viewport) / 2) + * cam.render_scale + - size / 2 + cam.bar_size; + + return SDL_FRect{ + .x = screen_pos.x, + .y = screen_pos.y, + .w = size.x, + .h = size.y, }; } void SDLContext::draw(const RenderContext & ctx) { + const Sprite::Data & data = ctx.sprite.data; SDL_RendererFlip render_flip - = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * ctx.sprite.flip.flip_x) - | (SDL_FLIP_VERTICAL * ctx.sprite.flip.flip_y)); + = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * data.flip.flip_x) + | (SDL_FLIP_VERTICAL * data.flip.flip_y)); SDL_Rect srcrect = this->get_src_rect(ctx.sprite); - SDL_Rect dstrect - = this->get_dst_rect(ctx.sprite, ctx.pos, ctx.cam, ctx.cam_pos, ctx.scale); - - this->set_color_texture(ctx.sprite.sprite_image, ctx.sprite.color); - SDL_RenderCopyEx(this->game_renderer.get(), ctx.sprite.sprite_image.texture.get(), - &srcrect, &dstrect, ctx.angle, NULL, render_flip); + SDL_FRect dstrect = this->get_dst_rect(SDLContext::DestinationRectangleData{ + .sprite = ctx.sprite, + .cam = ctx.cam, + .pos = ctx.pos, + .img_scale = ctx.scale, + }); + + double angle = ctx.angle + data.angle_offset; + + this->set_color_texture(ctx.sprite.texture, ctx.sprite.data.color); + SDL_RenderCopyExF(this->game_renderer.get(), ctx.sprite.texture.texture.get(), &srcrect, + &dstrect, angle, NULL, render_flip); } -void SDLContext::set_camera(const Camera & cam) { +SDLContext::CameraValues SDLContext::set_camera(const Camera & cam) { + const Camera::Data & cam_data = cam.data; + CameraValues ret_cam; // resize window int w, h; SDL_GetWindowSize(this->game_window.get(), &w, &h); @@ -270,42 +292,52 @@ void SDLContext::set_camera(const Camera & cam) { SDL_SetWindowSize(this->game_window.get(), cam.screen.x, cam.screen.y); } - double screen_aspect = cam.screen.x / cam.screen.y; - double viewport_aspect = cam.viewport_size.x / cam.viewport_size.y; + vec2 & zoomed_viewport = ret_cam.zoomed_viewport; + vec2 & bar_size = ret_cam.bar_size; + vec2 & render_scale = ret_cam.render_scale; + + zoomed_viewport = cam.viewport_size * cam_data.zoom; + float screen_aspect = static_cast<float>(cam.screen.x) / cam.screen.y; + float viewport_aspect = zoomed_viewport.x / zoomed_viewport.y; - SDL_Rect view; // calculate black bars if (screen_aspect > viewport_aspect) { - // letterboxing - view.h = cam.screen.y / cam.zoom; - view.w = cam.screen.y * viewport_aspect; - view.x = (cam.screen.x - view.w) / 2; - view.y = 0; - } else { // pillarboxing - view.h = cam.screen.x / viewport_aspect; - view.w = cam.screen.x / cam.zoom; - view.x = 0; - view.y = (cam.screen.y - view.h) / 2; + float scale = cam.screen.y / zoomed_viewport.y; + float adj_width = zoomed_viewport.x * scale; + float bar_width = (cam.screen.x - adj_width) / 2; + this->black_bars[0] = {0, 0, bar_width, (float) cam.screen.y}; + this->black_bars[1] = {(cam.screen.x - bar_width), 0, bar_width, (float) cam.screen.y}; + + bar_size = {bar_width, 0}; + render_scale.x = render_scale.y = scale; + } else { + // letterboxing + float scale = cam.screen.x / (cam.viewport_size.x * cam_data.zoom); + float adj_height = cam.viewport_size.y * scale; + float bar_height = (cam.screen.y - adj_height) / 2; + this->black_bars[0] = {0, 0, (float) cam.screen.x, bar_height}; + this->black_bars[1] + = {0, (cam.screen.y - bar_height), (float) cam.screen.x, bar_height}; + + bar_size = {0, bar_height}; + render_scale.x = render_scale.y = scale; } - // set drawing area - SDL_RenderSetViewport(this->game_renderer.get(), &view); - - SDL_RenderSetLogicalSize(this->game_renderer.get(), static_cast<int>(cam.viewport_size.x), - static_cast<int>(cam.viewport_size.y)); - // set bg color - SDL_SetRenderDrawColor(this->game_renderer.get(), cam.bg_color.r, cam.bg_color.g, - cam.bg_color.b, cam.bg_color.a); + SDL_SetRenderDrawColor(this->game_renderer.get(), cam_data.bg_color.r, cam_data.bg_color.g, + cam_data.bg_color.b, cam_data.bg_color.a); SDL_Rect bg = { .x = 0, .y = 0, - .w = static_cast<int>(cam.viewport_size.x), - .h = static_cast<int>(cam.viewport_size.y), + .w = cam.screen.x, + .h = cam.screen.y, }; + // fill bg color SDL_RenderFillRect(this->game_renderer.get(), &bg); + + return ret_cam; } uint64_t SDLContext::get_ticks() const { return SDL_GetTicks64(); } diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index a2b34c1..e232511 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -9,11 +9,9 @@ #include <functional> #include <memory> #include <string> -#include <utility> #include "api/Camera.h" #include "api/Color.h" -#include "api/Event.h" #include "api/KeyCodes.h" #include "api/Sprite.h" #include "api/Texture.h" @@ -27,16 +25,44 @@ class InputSystem; /** * \class SDLContext * \brief Facade for the SDL library - * + * * SDLContext is a singleton that handles the SDL window and renderer, provides methods for * event handling, and rendering to the screen. It is never used directly by the user */ class SDLContext { public: + //! data that the camera component cannot hold + struct CameraValues { + + //! zoomed in viewport in game_units + vec2 zoomed_viewport; + + /** + * \brief scaling factor + * + * depending on the black bars type will the scaling be different. + * - letterboxing --> scaling on the y-as + * - pillarboxing --> scaling on the x-as + */ + vec2 render_scale; + + /** + * \brief size of calculated black bars + * + * depending on the black bars type will the size be different + * - lettorboxing --> {0, bar_height} + * - pillarboxing --> {bar_width , 0} + */ + vec2 bar_size; + + //! Calculated camera position + vec2 cam_pos; + }; + + //! rendering data needed to render on screen struct RenderContext { const Sprite & sprite; - const Camera & cam; - const vec2 & cam_pos; + const CameraValues & cam; const vec2 & pos; const double & angle; const double & scale; @@ -82,21 +108,21 @@ private: friend class InputSystem; /** * \brief Retrieves a list of all events from the SDL context. - * + * * This method retrieves all the events from the SDL context that are currently * available. It is primarily used by the InputSystem to process various * input events such as mouse clicks, mouse movements, and keyboard presses. - * + * * \return Events that occurred since last call to `get_events()` */ std::vector<SDLContext::EventData> get_events(); /** * \brief Converts an SDL key code to the custom Keycode type. - * + * * This method maps an SDL key code to the corresponding `Keycode` enum value, * which is used internally by the system to identify the keys. - * + * * \param sdl_key The SDL key code to convert. * \return The corresponding `Keycode` value or `Keycode::NONE` if the key is unrecognized. */ @@ -104,18 +130,16 @@ private: /** * \brief Converts an SDL mouse button code to the custom MouseButton type. - * - * This method maps an SDL mouse button code to the corresponding `MouseButton` + * + * This method maps an SDL mouse button code to the corresponding `MouseButton` * enum value, which is used internally by the system to identify mouse buttons. - * + * * \param sdl_button The SDL mouse button code to convert. * \return The corresponding `MouseButton` value or `MouseButton::NONE` if the key is unrecognized */ MouseButton sdl_to_mousebutton(Uint8 sdl_button); private: - //! Will only use get_ticks - friend class AnimatorSystem; //! Will only use delay friend class LoopTimer; /** @@ -170,7 +194,7 @@ private: /** * \brief Draws a sprite to the screen using the specified transform and camera. - * \param RenderCtx Reference to rendering data to draw + * \param RenderContext Reference to rendering data to draw */ void draw(const RenderContext & ctx); @@ -184,9 +208,16 @@ private: * \brief sets the background of the camera (will be adjusted in future PR) * \param camera Reference to the Camera object. */ - void set_camera(const Camera & camera); + CameraValues set_camera(const Camera & camera); private: + //! the data needed to construct a sdl dst rectangle + struct DestinationRectangleData { + const Sprite & sprite; + const CameraValues & cam; + const vec2 & pos; + const double & img_scale; + }; /** * \brief calculates the sqaure size of the image * @@ -202,15 +233,14 @@ private: * \param pos the pos in world units * \param cam the camera of the current scene * \param cam_pos the current postion of the camera - * \param img_scale the image multiplier for increasing img size + * \param img_scale the image multiplier for increasing img size * \return sdl rectangle to draw a dst image to draw on the screen */ - SDL_Rect get_dst_rect(const Sprite & sprite, const vec2 & pos, const Camera & cam, - const vec2 & cam_pos, const double & img_scale) const; + SDL_FRect get_dst_rect(const DestinationRectangleData & data) const; /** * \brief Set an additional color value multiplied into render copy operations. * - * \param texture the given texture to adjust + * \param texture the given texture to adjust * \param color the color data for the texture */ void set_color_texture(const Texture & texture, const Color & color); @@ -221,6 +251,9 @@ private: //! renderer for the crepe engine std::unique_ptr<SDL_Renderer, std::function<void(SDL_Renderer *)>> game_renderer; + + //! black bars rectangle to draw + SDL_FRect black_bars[2] = {}; }; } // namespace crepe diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index 4c68f32..ee43d94 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -35,7 +35,7 @@ public: 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. |