diff options
| -rw-r--r-- | src/crepe/api/LoopTimer.h | 2 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.cpp | 203 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.h | 127 | 
3 files changed, 239 insertions, 93 deletions
diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h index 584a408..8d95921 100644 --- a/src/crepe/api/LoopTimer.h +++ b/src/crepe/api/LoopTimer.h @@ -78,4 +78,4 @@ double elapsed_fixed_time = 0;      ///< Total elapsed time for fixed updates  uint64_t last_frame_time = 0;       ///< Time of the last frame  }; -} // namespace crepe::api +} // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 8da93e9..17ced0c 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,126 @@ SDLContext::SDLContext() {  	}  } -void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer); } +SDLContext::~SDLContext() { +	dbg_trace(); + +	this->game_renderer.reset(); +	this->game_window.reset(); + +	// 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) { +void SDLContext::draw(const Sprite & sprite, const Transform & transform, +					  const Camera & cam) { -	static SDL_RendererFlip render_flip +	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; +} +void SDLContext::delay(int ms) const{ +	SDL_Delay(ms);  } diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index f1ba8a6..6c57ef9 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -1,48 +1,155 @@  #pragma once +#include <SDL2/SDL_keycode.h>  #include <SDL2/SDL_render.h>  #include <SDL2/SDL_video.h> +#include <functional> +#include <memory> +#include <string>  #include "../api/Sprite.h"  #include "../api/Transform.h" -#include "../system/RenderSystem.h" +#include "api/Camera.h" + +// FIXME: this needs to be removed +const int SCREEN_WIDTH = 640; +const int SCREEN_HEIGHT = 480;  namespace crepe { +// TODO: SDL_Keycode is defined in a header not distributed with crepe, which +// means this typedef is unusable when crepe is packaged. Wouter will fix this +// later. +typedef SDL_Keycode CREPE_KEYCODES; +  class Texture; +class LoopManager; + +/** + * \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: -	// singleton +	/** +	 * \brief Gets the singleton instance of SDLContext. +	 * \return Reference to the SDLContext instance. +	 */  	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: +	//! will only use handle_events +	friend class LoopManager; +	/** +	 * \brief Handles SDL events such as window close and input. +	 * \param running Reference to a boolean flag that controls the main loop. +	 */  	void handle_events(bool & running);  private: +	//! Will only use get_ticks +	friend class AnimatorSystem; +	friend class LoopTimer; +	/** +	 * \brief Gets the current SDL ticks since the program started. +	 * \return Current ticks in milliseconds as a constant uint64_t. +	 */ +	uint64_t get_ticks() const; +	/** +	 * \brief Pauses the execution for a specified duration. +	 * +	 * This function uses SDL's delay function to halt the program execution +	 * for a given number of milliseconds, allowing for frame rate control +	 * or other timing-related functionality. +	 * +	 * \param ms Duration of the delay in milliseconds. +	 */ +	void delay(int ms) const; +private: +	/** +	 * \brief Constructs an SDLContext instance. +	 * Initializes SDL, creates a window and renderer. +	 */  	SDLContext(); -	virtual ~SDLContext(); + +	/** +	 * \brief Destroys the SDLContext instance. +	 * Cleans up SDL resources, including the window and renderer. +	 */ +	~SDLContext();  private: +	//! Will use the funtions: texture_from_path, get_width,get_height.  	friend class Texture; -	SDL_Texture * texture_from_path(const char *); -	//SDL_Texture* setTextureFromPath(const char*, SDL_Rect& clip, const int row, const int col); + +	//! Will use the funtions: texture_from_path, get_width,get_height. +	friend class Animator; + +	/** +	 * \brief Loads a texture from a file path. +	 * \param path Path to the image file. +	 * \return Pointer to the created SDL_Texture. +	 */ +	std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> +	texture_from_path(const std::string & path); +	/** +	 * \brief Gets the width of a texture. +	 * \param texture Reference to the Texture object. +	 * \return Width of the texture as an integer. +	 */ +	int get_width(const Texture &) const; + +	/** +	 * \brief Gets the height of a texture. +	 * \param texture Reference to the Texture object. +	 * \return Height of the texture as an integer. +	 */ +	int get_height(const Texture &) const;  private: +	//! Will use draw,clear_screen, present_screen, camera.  	friend class RenderSystem; -	void draw(const Sprite &, const Transform &); + +	/** +	 * \brief Draws a sprite to the screen using the specified transform and camera. +	 * \param sprite Reference to the Sprite to draw. +	 * \param transform Reference to the Transform for positioning. +	 * \param camera Reference to the Camera for view adjustments. +	 */ +	void draw(const Sprite & sprite, const Transform & transform, +			  const Camera & camera); + +	//! Clears the screen, preparing for a new frame.  	void clear_screen(); + +	//! Presents the rendered frame to the screen.  	void present_screen(); +	/** +	 * \brief Sets the current camera for rendering. +	 * \param camera Reference to the Camera object. +	 */ +	void camera(const Camera & camera); +  private: -	SDL_Window * game_window = nullptr; -	SDL_Renderer * game_renderer = nullptr; +	//! sdl Window +	std::unique_ptr<SDL_Window, std::function<void(SDL_Window *)>> game_window; + +	//! renderer for the crepe engine +	std::unique_ptr<SDL_Renderer, std::function<void(SDL_Renderer *)>> +		game_renderer; + +	//! viewport for the camera window +	SDL_Rect viewport = {0, 0, 640, 480};  };  } // namespace crepe  |