diff options
Diffstat (limited to 'src/crepe/facade/SDLContext.cpp')
-rw-r--r-- | src/crepe/facade/SDLContext.cpp | 167 |
1 files changed, 102 insertions, 65 deletions
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 4a0ac1a..c01d118 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -1,5 +1,6 @@ #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> +#include <SDL2/SDL_keycode.h> #include <SDL2/SDL_rect.h> #include <SDL2/SDL_render.h> #include <SDL2/SDL_surface.h> @@ -8,17 +9,17 @@ #include <cstddef> #include <cstdint> #include <functional> -#include <iostream> #include <memory> -#include <string> -#include <sys/types.h> +#include <stdexcept> +#include "../api/Camera.h" +#include "../api/Config.h" #include "../api/Sprite.h" #include "../api/Texture.h" -#include "../api/Transform.h" #include "../util/Log.h" #include "SDLContext.h" +#include "types.h" using namespace crepe; using namespace std; @@ -30,31 +31,25 @@ SDLContext & SDLContext::get_instance() { 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; + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError())); } + + auto & cfg = Config::get_instance().window_settings; SDL_Window * tmp_window - = SDL_CreateWindow("Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - this->viewport.w, this->viewport.h, 0); + = SDL_CreateWindow(cfg.window_title.c_str(), SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, cfg.default_size.x, cfg.default_size.y, 0); if (!tmp_window) { - // FIXME: throw exception - std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; - return; + throw runtime_error(format("SDLContext: SDL_Window error: {}", SDL_GetError())); } this->game_window = {tmp_window, [](SDL_Window * window) { SDL_DestroyWindow(window); }}; SDL_Renderer * tmp_renderer = SDL_CreateRenderer(this->game_window.get(), -1, SDL_RENDERER_ACCELERATED); if (!tmp_renderer) { - // FIXME: throw exception - std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() - << std::endl; - SDL_DestroyWindow(this->game_window.get()); - return; + throw runtime_error( + format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); } this->game_renderer @@ -62,9 +57,7 @@ SDLContext::SDLContext() { 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; + throw runtime_error("SDLContext: SDL_image could not initialize!"); } } @@ -80,7 +73,6 @@ SDLContext::~SDLContext() { IMG_Quit(); SDL_Quit(); } - void SDLContext::handle_events(bool & running) { //TODO: wouter i need events /* @@ -102,56 +94,96 @@ void SDLContext::handle_events(bool & running) { */ } -void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } +void SDLContext::clear_screen() { + SDL_SetRenderDrawColor(this->game_renderer.get(), 0, 0, 0, 255); + SDL_RenderClear(this->game_renderer.get()); +} void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } -void SDLContext::set_rbg_texture(const std::shared_ptr<Texture>& texture, const uint8_t& r, const uint8_t& g, const uint8_t& b){ - SDL_SetTextureColorMod(texture->texture.get(), r, g, b); +SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { + return SDL_Rect{ + .x = sprite.mask.x, + .y = sprite.mask.y, + .w = sprite.mask.w, + .h = sprite.mask.h, + }; } -void SDLContext::set_alpha_texture(const std::shared_ptr<Texture>& texture, const uint8_t& alpha){ - SDL_SetTextureAlphaMod(texture->texture.get(), alpha ); +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; + + width *= img_scale * cam.zoom; + height *= img_scale * cam.zoom; + + 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, + }; } -void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { +void SDLContext::draw(const RenderContext & ctx) { SDL_RendererFlip render_flip - = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) - | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); - - this->set_rbg_texture(sprite.sprite_image, sprite.color.r, sprite.color.g, sprite.color.b); - this->set_alpha_texture(sprite.sprite_image, sprite.color.a); - - double adjusted_x = (transform.position.x - cam.x) * cam.zoom; - double adjusted_y = (transform.position.y - cam.y) * cam.zoom; - double adjusted_w = sprite.sprite_rect.w * transform.scale * cam.zoom; - double adjusted_h = sprite.sprite_rect.h * transform.scale * cam.zoom; - - SDL_Rect srcrect = { - .x = sprite.sprite_rect.x, - .y = sprite.sprite_rect.y, - .w = sprite.sprite_rect.w, - .h = sprite.sprite_rect.h, - }; + = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * ctx.sprite.flip.flip_x) + | (SDL_FLIP_VERTICAL * ctx.sprite.flip.flip_y)); - SDL_Rect dstrect = { - .x = static_cast<int>(adjusted_x), - .y = static_cast<int>(adjusted_y), - .w = static_cast<int>(adjusted_w), - .h = static_cast<int>(adjusted_h), - }; + 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); - SDL_RenderCopyEx(this->game_renderer.get(), sprite.sprite_image->texture.get(), &srcrect, - &dstrect, transform.rotation, NULL, render_flip); + SDL_RenderCopyEx(this->game_renderer.get(), ctx.sprite.sprite_image.texture.get(), + &srcrect, &dstrect, ctx.angle, NULL, render_flip); } -void SDLContext::camera(const Camera & cam) { - this->viewport.w = static_cast<int>(cam.aspect_width); - this->viewport.h = static_cast<int>(cam.aspect_height); - this->viewport.x = static_cast<int>(cam.x) - (SCREEN_WIDTH / 2); - this->viewport.y = static_cast<int>(cam.y) - (SCREEN_HEIGHT / 2); +void SDLContext::set_camera(const Camera & cam) { + // resize window + int w, h; + SDL_GetWindowSize(this->game_window.get(), &w, &h); + if (w != cam.screen.x || h != cam.screen.y) { + 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; + + 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; + } + // 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_Rect bg = { + .x = 0, + .y = 0, + .w = static_cast<int>(cam.viewport_size.x), + .h = static_cast<int>(cam.viewport_size.y), + }; + // fill bg color + SDL_RenderFillRect(this->game_renderer.get(), &bg); } uint64_t SDLContext::get_ticks() const { return SDL_GetTicks64(); } @@ -160,9 +192,8 @@ std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> SDLContext::texture_from_path(const std::string & path) { SDL_Surface * tmp = IMG_Load(path.c_str()); - if (tmp == nullptr) { - tmp = IMG_Load("../asset/texture/ERROR.png"); - } + if (tmp == nullptr) + throw runtime_error(format("SDLContext: IMG_Load error: {}", SDL_GetError())); std::unique_ptr<SDL_Surface, std::function<void(SDL_Surface *)>> img_surface; img_surface = {tmp, [](SDL_Surface * surface) { SDL_FreeSurface(surface); }}; @@ -171,7 +202,7 @@ SDLContext::texture_from_path(const std::string & path) { = SDL_CreateTextureFromSurface(this->game_renderer.get(), img_surface.get()); if (tmp_texture == nullptr) { - throw runtime_error(format("Texture cannot be load from {}", path)); + throw runtime_error(format("SDLContext: Texture cannot be load from {}", path)); } std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> img_texture; @@ -179,14 +210,20 @@ SDLContext::texture_from_path(const std::string & path) { return img_texture; } -int SDLContext::get_width(const Texture & ctx) { +int SDLContext::get_width(const Texture & ctx) const { int w; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &w, NULL); return w; } -int SDLContext::get_height(const Texture & ctx) { +int SDLContext::get_height(const Texture & ctx) const { int h; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h); return h; } void SDLContext::delay(int ms) const { SDL_Delay(ms); } +void SDLContext::set_rbg_texture(const std::shared_ptr<Texture>& texture, const uint8_t& r, const uint8_t& g, const uint8_t& b){ + SDL_SetTextureColorMod(texture->texture.get(), r, g, b); +} +void SDLContext::set_alpha_texture(const std::shared_ptr<Texture>& texture, const uint8_t& alpha){ + SDL_SetTextureAlphaMod(texture->texture.get(), alpha ); +}
\ No newline at end of file |