diff options
Diffstat (limited to 'src/crepe/facade/SDLContext.cpp')
-rw-r--r-- | src/crepe/facade/SDLContext.cpp | 200 |
1 files changed, 118 insertions, 82 deletions
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 8da93e9..c4c96e2 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -1,16 +1,22 @@ #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> +#include <SDL2/SDL_rect.h> #include <SDL2/SDL_render.h> #include <SDL2/SDL_surface.h> #include <SDL2/SDL_video.h> #include <cmath> #include <cstddef> +#include <functional> #include <iostream> +#include <memory> +#include <string> +#include <utility> #include "../api/Sprite.h" #include "../api/Texture.h" #include "../api/Transform.h" #include "../util/log.h" +#include "Exception.h" #include "SDLContext.h" @@ -21,34 +27,6 @@ SDLContext & SDLContext::get_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 @@ -59,26 +37,32 @@ SDLContext::SDLContext() { << std::endl; return; } - - this->game_window = SDL_CreateWindow( + SDL_Window * tmp_window = SDL_CreateWindow( "Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - 1920, 1080, SDL_WINDOW_SHOWN); - if (!this->game_window) { + this->viewport.w, this->viewport.h, 0); + if (!tmp_window) { // FIXME: throw exception std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; + return; } + this->game_window + = {tmp_window, [](SDL_Window * window) { SDL_DestroyWindow(window); }}; - this->game_renderer - = SDL_CreateRenderer(this->game_window, -1, SDL_RENDERER_ACCELERATED); - if (!this->game_renderer) { + 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); + SDL_DestroyWindow(this->game_window.get()); return; } + this->game_renderer = {tmp_renderer, [](SDL_Renderer * renderer) { + SDL_DestroyRenderer(renderer); + }}; + int img_flags = IMG_INIT_PNG; if (!(IMG_Init(img_flags) & img_flags)) { // FIXME: throw exception @@ -87,71 +71,123 @@ SDLContext::SDLContext() { } } -void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer); } +SDLContext::~SDLContext() { + dbg_trace(); -void SDLContext::draw(const Sprite & sprite, const Transform & transform) { + this->game_renderer.reset(); + this->game_window.reset(); - static SDL_RendererFlip render_flip + // 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::handle_events(bool & running) { + //TODO: wouter i need events + /* + SDL_Event event; + SDL_PollEvent(&event); + switch (event.type) { + case SDL_QUIT: + running = false; + break; + case SDL_KEYDOWN: + triggerEvent(KeyPressedEvent(getCustomKey(event.key.keysym.sym))); + break; + case SDL_MOUSEBUTTONDOWN: + int x, y; + SDL_GetMouseState(&x, &y); + triggerEvent(MousePressedEvent(x, y)); + break; + } + */ +} + +void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } +void SDLContext::present_screen() { + SDL_RenderPresent(this->game_renderer.get()); +} + +void SDLContext::draw(const Sprite & sprite, const Transform & transform, + const Camera & cam) { + + 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 + 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_Rect dstrect = { - .x = static_cast<int>(transform.position.x), - .y = static_cast<int>(transform.position.y), - .w = static_cast<int>(w * transform.scale), - .h = static_cast<int>(h * transform.scale), + .x = static_cast<int>(adjusted_x), + .y = static_cast<int>(adjusted_y), + .w = static_cast<int>(adjusted_w), + .h = static_cast<int>(adjusted_h), }; - double degrees = transform.rotation * 180 / M_PI; - SDL_RenderCopyEx(this->game_renderer, sprite.sprite_image->texture, NULL, - &dstrect, degrees, NULL, render_flip); + SDL_RenderCopyEx(this->game_renderer.get(), + sprite.sprite_image->texture.get(), &srcrect, + + &dstrect, transform.rotation, NULL, render_flip); } -/* -SDL_Texture * SDLContext::setTextureFromPath(const char * path, SDL_Rect & clip, - const int row, const int col) { - dbg_trace(); +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); - SDL_Surface * tmp = IMG_Load(path); - if (!tmp) { - std::cerr << "Error surface " << IMG_GetError << std::endl; - } + SDL_SetRenderDrawColor(this->game_renderer.get(), cam.bg_color.r, + cam.bg_color.g, cam.bg_color.b, cam.bg_color.a); +} - clip. - w = tmp->w / col; - clip.h = tmp->h / row; +uint64_t SDLContext::get_ticks() const { return SDL_GetTicks64(); } - SDL_Texture * CreatedTexture - = SDL_CreateTextureFromSurface(this->game_renderer, tmp); +std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> +SDLContext::texture_from_path(const std::string & path) { - if (!CreatedTexture) { - std::cerr << "Error could not create texture " << IMG_GetError - << std::endl; + SDL_Surface * tmp = IMG_Load(path.c_str()); + if (tmp == nullptr) { + throw Exception("surface cannot be load from %s", path.c_str()); } - SDL_FreeSurface(tmp); - return CreatedTexture; -} -*/ + std::unique_ptr<SDL_Surface, std::function<void(SDL_Surface *)>> + img_surface; + img_surface + = {tmp, [](SDL_Surface * surface) { SDL_FreeSurface(surface); }}; -SDL_Texture * SDLContext::texture_from_path(const char * path) { - dbg_trace(); + SDL_Texture * tmp_texture = SDL_CreateTextureFromSurface( + this->game_renderer.get(), img_surface.get()); - SDL_Surface * tmp = IMG_Load(path); - if (!tmp) { - std::cerr << "Error surface " << IMG_GetError << std::endl; + if (tmp_texture == nullptr) { + throw Exception("Texture cannot be load from %s", path.c_str()); } - 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); + std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> + img_texture; + img_texture = {tmp_texture, + [](SDL_Texture * texture) { SDL_DestroyTexture(texture); }}; - return created_texture; + return img_texture; +} +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) const { + int h; + SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h); + return h; } |