diff options
| -rw-r--r-- | asset/texture/img.png | bin | 92742 -> 11476 bytes | |||
| -rw-r--r-- | asset/texture/test_ap43.png | bin | 0 -> 2394 bytes | |||
| -rw-r--r-- | contributing.md | 2 | ||||
| -rw-r--r-- | src/crepe/api/Animator.cpp | 13 | ||||
| -rw-r--r-- | src/crepe/api/Animator.h | 6 | ||||
| -rw-r--r-- | src/crepe/api/Camera.cpp | 10 | ||||
| -rw-r--r-- | src/crepe/api/Camera.h | 25 | ||||
| -rw-r--r-- | src/crepe/api/Config.h | 10 | ||||
| -rw-r--r-- | src/crepe/api/Sprite.cpp | 19 | ||||
| -rw-r--r-- | src/crepe/api/Sprite.h | 64 | ||||
| -rw-r--r-- | src/crepe/api/Texture.cpp | 22 | ||||
| -rw-r--r-- | src/crepe/api/Texture.h | 16 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.cpp | 191 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.h | 62 | ||||
| -rw-r--r-- | src/crepe/system/AnimatorSystem.cpp | 10 | ||||
| -rw-r--r-- | src/crepe/system/AnimatorSystem.h | 3 | ||||
| -rw-r--r-- | src/crepe/system/RenderSystem.cpp | 48 | ||||
| -rw-r--r-- | src/crepe/system/RenderSystem.h | 28 | ||||
| -rw-r--r-- | src/crepe/types.h | 2 | ||||
| -rw-r--r-- | src/example/rendering_particle.cpp | 29 | ||||
| -rw-r--r-- | src/test/ParticleTest.cpp | 6 | ||||
| -rw-r--r-- | src/test/RenderSystemTest.cpp | 58 | 
22 files changed, 323 insertions, 301 deletions
| diff --git a/asset/texture/img.png b/asset/texture/img.pngBinary files differ index 43b1eca..649a3f1 100644 --- a/asset/texture/img.png +++ b/asset/texture/img.png diff --git a/asset/texture/test_ap43.png b/asset/texture/test_ap43.pngBinary files differ new file mode 100644 index 0000000..e758ed7 --- /dev/null +++ b/asset/texture/test_ap43.png diff --git a/contributing.md b/contributing.md index 0a90e86..b0f623b 100644 --- a/contributing.md +++ b/contributing.md @@ -17,6 +17,8 @@ that you can click on to open them.    working/compiling version of the project  - Pull requests for new code include either automated tests for the new code or    an explanation as to why the code can not (reliably) be tested +- Non-bugfix pull requests must be approved by at least 2 reviewers before being +  merged  <!--  - TODO: tagging / versions diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index 464b0fd..45f67f6 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -14,11 +14,14 @@ Animator::Animator(game_object_id_t id, Sprite & ss, int row, int col, int col_a  	  col(col) {  	dbg_trace(); -	animator_rect = spritesheet.sprite_rect; -	animator_rect.h /= col; -	animator_rect.w /= row; -	animator_rect.x = 0; -	animator_rect.y = col_animator * animator_rect.h; +	this->spritesheet.mask.h /= col; +	this->spritesheet.mask.w /= row; +	this->spritesheet.mask.x = 0; +	this->spritesheet.mask.y = col_animator * this->spritesheet.mask.h;  	this->active = false; + +	// need to do this for to get the aspect ratio for a single clipping in the spritesheet +	this->spritesheet.aspect_ratio +		= static_cast<double>(this->spritesheet.mask.w) / this->spritesheet.mask.h;  }  Animator::~Animator() { dbg_trace(); } diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h index 53f4b91..6c506aa 100644 --- a/src/crepe/api/Animator.h +++ b/src/crepe/api/Animator.h @@ -40,10 +40,6 @@ public:  	Animator(uint32_t id, Sprite & spritesheet, int row, int col, int col_animate);  	~Animator(); // dbg_trace -	Animator(const Animator &) = delete; -	Animator(Animator &&) = delete; -	Animator & operator=(const Animator &) = delete; -	Animator & operator=(Animator &&) = delete;  private:  	//! A reference to the Sprite sheet containing the animation frames. @@ -61,8 +57,6 @@ private:  	//! The current row being animated.  	int curr_row = 0; -	Rect animator_rect; -  	//TODO: Is this necessary?  	//int fps; diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp index 5835bdd..39d8ab0 100644 --- a/src/crepe/api/Camera.cpp +++ b/src/crepe/api/Camera.cpp @@ -1,3 +1,4 @@ +#include "types.h"  #include "util/Log.h"  #include "Camera.h" @@ -6,9 +7,14 @@  using namespace crepe; -Camera::Camera(game_object_id_t id, const Color & bg_color) +Camera::Camera(game_object_id_t id, const Color & bg_color, const ivec2 & screen, +			   const vec2 & viewport_size, const double & zoom, const vec2 & offset)  	: Component(id), -	  bg_color(bg_color) { +	  bg_color(bg_color), +	  offset(offset), +	  screen(screen), +	  viewport_size(viewport_size), +	  zoom(zoom) {  	dbg_trace();  } diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h index e0cda34..2d8fa48 100644 --- a/src/crepe/api/Camera.h +++ b/src/crepe/api/Camera.h @@ -2,6 +2,7 @@  #include "Color.h"  #include "Component.h" +#include "types.h"  namespace crepe { @@ -20,33 +21,31 @@ public:  	 * \param id Unique identifier for the camera component.  	 * \param bg_color Background color for the camera view.  	 */ -	Camera(game_object_id_t id, const Color & bg_color); +	Camera(game_object_id_t id, const Color & bg_color, const ivec2 & screen, +		   const vec2 & viewport_size, const double & zoom, const vec2 & offset = {0, 0});  	~Camera(); // dbg_trace only  public:  	//! Background color of the camera view. -	Color bg_color; +	const Color bg_color; -	//! Aspect ratio height for the camera. -	double aspect_height = 480; +	//! offset postion from the game object transform component +	vec2 offset; -	//! Aspect ratio width for the camera. -	double aspect_width = 640; +	//! screen the display size in pixels ( output resolution ) +	const ivec2 screen; -	//! X-coordinate of the camera position. -	double x = 0.0; - -	//! Y-coordinate of the camera position. -	double y = 0.0; +	//! viewport is the area of the world visible through the camera (in world units) +	const vec2 viewport_size;  	//! Zoom level of the camera view. -	double zoom = 1.0; +	const double zoom;  public:  	/**  	 * \brief Gets the maximum number of camera instances allowed.  	 * \return Maximum instance count as an integer.  	 */ -	virtual int get_instances_max() const { return 10; } +	virtual int get_instances_max() const { return 1; }  };  } // namespace crepe diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 0c9d116..225e9b9 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -1,6 +1,8 @@  #pragma once  #include "../util/Log.h" +#include "types.h" +#include <string>  namespace crepe { @@ -62,6 +64,14 @@ public:  		double gravity = 1;  	} physics; +	//! default window settings +	struct { +		//TODO make this constexpr because this will never change +		ivec2 default_size = {1080, 720}; +		std::string window_title = "Jetpack joyride clone"; + +	} window_settings; +  	//! Asset loading options  	struct {  		/** diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index bd2d5cf..0a2ad4c 100644 --- a/src/crepe/api/Sprite.cpp +++ b/src/crepe/api/Sprite.cpp @@ -1,7 +1,7 @@ -#include <memory> +#include <cmath> +#include <utility>  #include "../util/Log.h" -#include "facade/SDLContext.h"  #include "Component.h"  #include "Sprite.h" @@ -10,16 +10,21 @@  using namespace std;  using namespace crepe; -Sprite::Sprite(game_object_id_t id, const shared_ptr<Texture> image, const Color & color, -			   const FlipSettings & flip) +Sprite::Sprite(game_object_id_t id, Texture & image, const Color & color, +			   const FlipSettings & flip, int sort_layer, int order_layer, int height)  	: Component(id),  	  color(color),  	  flip(flip), -	  sprite_image(image) { +	  sprite_image(std::move(image)), +	  sorting_in_layer(sort_layer), +	  order_in_layer(order_layer), +	  height(height) { +  	dbg_trace(); -	this->sprite_rect.w = sprite_image->get_width(); -	this->sprite_rect.h = sprite_image->get_height(); +	this->mask.w = sprite_image.get_size().x; +	this->mask.h = sprite_image.get_size().y; +	this->aspect_ratio = static_cast<double>(this->mask.w) / this->mask.h;  }  Sprite::~Sprite() { dbg_trace(); } diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index 74a55d4..a0e90a0 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -1,6 +1,6 @@  #pragma once -#include <memory> +#include <cstdint>  #include "../Component.h" @@ -9,18 +9,6 @@  namespace crepe { -struct Rect { -	int w = 0; -	int h = 0; -	int x = 0; -	int y = 0; -}; - -struct FlipSettings { -	bool flip_x = false; -	bool flip_y = false; -}; -  class SDLContext;  class Animator;  class AnimatorSystem; @@ -34,6 +22,12 @@ class AnimatorSystem;  class Sprite : public Component {  public: +	struct FlipSettings { +		bool flip_x = false; +		bool flip_y = false; +	}; + +public:  	// TODO: Loek comment in github #27 will be looked another time  	// about shared_ptr Texture  	/** @@ -42,9 +36,12 @@ public:  	 * \param image Shared pointer to the texture for this sprite.  	 * \param color Color tint applied to the sprite.  	 * \param flip Flip settings for horizontal and vertical orientation. +	 * \param order_layer decides the sorting in layer of the sprite. +	 * \param sort_layer decides the order in layer of the sprite. +	 * \param height the height of the image in game units  	 */ -	Sprite(game_object_id_t id, const std::shared_ptr<Texture> image, const Color & color, -		   const FlipSettings & flip); +	Sprite(game_object_id_t id, Texture & image, const Color & color, +		   const FlipSettings & flip, int sort_layer, int order_layer, int height);  	/**  	 * \brief Destroys the Sprite instance. @@ -52,38 +49,49 @@ public:  	~Sprite();  	//! Texture used for the sprite -	const std::shared_ptr<Texture> sprite_image; +	const Texture sprite_image; +  	//! Color tint of the sprite  	Color color; +  	//! Flip settings for the sprite  	FlipSettings flip; +  	//! Layer sorting level of the sprite -	uint8_t sorting_in_layer = 0; +	const int sorting_in_layer;  	//! Order within the sorting layer -	uint8_t order_in_layer = 0; +	const int order_in_layer; + +	//! height in world units +	const int height; -public:  	/** -	 * \brief Gets the maximum number of instances allowed for this sprite. -	 * \return Maximum instance count as an integer. +	 * \aspect_ratio ratio of the img so that scaling will not become weird  	 * -	 * For now is this number randomly picked. I think it will eventually be 1.  +	 * cannot be const because if Animator component is addded then ratio becomes scuffed and +	 * does it need to be calculated again in the Animator  	 */ -	virtual int get_instances_max() const { return 10; } +	double aspect_ratio;  private: -	//! Reads the sprite_rect of sprite +	//! Reads the mask of sprite  	friend class SDLContext; -	//! Reads the all the variables plus the  sprite_rect +	//! Reads the all the variables plus the  mask  	friend class Animator; -	//! Reads the all the variables plus the  sprite_rect +	//! Reads the all the variables plus the  mask  	friend class AnimatorSystem; +	struct Rect { +		int w = 0; +		int h = 0; +		int x = 0; +		int y = 0; +	};  	//! Render area of the sprite this will also be adjusted by the AnimatorSystem if an Animator -	// object is present in GameObject -	Rect sprite_rect; +	// object is present in GameObject. this is in sprite pixels +	Rect mask;  };  } // namespace crepe diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index 264d7b1..2b56271 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -1,10 +1,9 @@ -#include <SDL2/SDL_render.h> -  #include "../facade/SDLContext.h"  #include "../util/Log.h"  #include "Asset.h"  #include "Texture.h" +#include "types.h"  using namespace crepe;  using namespace std; @@ -19,16 +18,21 @@ Texture::~Texture() {  	this->texture.reset();  } +Texture::Texture(Texture && other) noexcept : texture(std::move(other.texture)) {} + +Texture & Texture::operator=(Texture && other) noexcept { +	if (this != &other) { +		texture = std::move(other.texture); +	} +	return *this; +} +  void Texture::load(const Asset & res) {  	SDLContext & ctx = SDLContext::get_instance();  	this->texture = ctx.texture_from_path(res.get_path());  } -int Texture::get_width() const { -	if (this->texture == nullptr) return 0; -	return SDLContext::get_instance().get_width(*this); -} -int Texture::get_height() const { -	if (this->texture == nullptr) return 0; -	return SDLContext::get_instance().get_height(*this); +ivec2 Texture::get_size() const { +	if (this->texture == nullptr) return {}; +	return SDLContext::get_instance().get_size(*this);  } diff --git a/src/crepe/api/Texture.h b/src/crepe/api/Texture.h index b4f7d07..1817910 100644 --- a/src/crepe/api/Texture.h +++ b/src/crepe/api/Texture.h @@ -8,6 +8,7 @@  #include <memory>  #include "Asset.h" +#include "types.h"  namespace crepe { @@ -36,17 +37,16 @@ public:  	~Texture();  	// FIXME: this constructor shouldn't be necessary because this class doesn't manage memory -	/** -	 * \brief Gets the width of the texture. -	 * \return Width of the texture in pixels. -	 */ -	int get_width() const; +	Texture(Texture && other) noexcept; +	Texture & operator=(Texture && other) noexcept; +	Texture(const Texture &) = delete; +	Texture & operator=(const Texture &) = delete;  	/** -	 * \brief Gets the height of the texture. -	 * \return Height of the texture in pixels. +	 * \brief Gets the width and height of the texture. +	 * \return Width and height of the texture in pixels.  	 */ -	int get_height() const; +	ivec2 get_size() const;  private:  	/** diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 735ed70..9b4595e 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -1,4 +1,5 @@  #include <SDL2/SDL.h> +#include <SDL2/SDL_blendmode.h>  #include <SDL2/SDL_image.h>  #include <SDL2/SDL_keycode.h>  #include <SDL2/SDL_rect.h> @@ -8,20 +9,20 @@  #include <array>  #include <cmath>  #include <cstddef> +#include <cstdint>  #include <functional> +#include <iostream>  #include <memory>  #include <stdexcept> -#include <string>  #include "../api/Camera.h" -#include "../api/EventManager.h"  #include "../api/Sprite.h"  #include "../api/Texture.h" -#include "../api/Transform.h" -#include "../api/Vector2.h"  #include "../util/Log.h"  #include "SDLContext.h" +#include "api/Color.h" +#include "types.h"  using namespace crepe;  using namespace std; @@ -33,14 +34,15 @@ SDLContext & SDLContext::get_instance() {  SDLContext::SDLContext() {  	dbg_trace(); -	// FIXME: read window defaults from config manager  	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) {  		throw runtime_error(format("SDLContext: SDL_Window error: {}", SDL_GetError()));  	} @@ -212,68 +214,93 @@ MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) {  }  void SDLContext::clear_screen() { SDL_RenderClear(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{ -		.x = sprite.sprite_rect.x, -		.y = sprite.sprite_rect.y, -		.w = sprite.sprite_rect.w, -		.h = sprite.sprite_rect.h, +		.x = sprite.mask.x, +		.y = sprite.mask.y, +		.w = sprite.mask.w, +		.h = sprite.mask.h,  	};  } -SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const vec2 & pos, -								  const double & scale, const Camera & cam) const { +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; -	double adjusted_w = sprite.sprite_rect.w * scale * cam.zoom; -	double adjusted_h = sprite.sprite_rect.h * scale * cam.zoom; -	double adjusted_x = (pos.x - cam.x) * cam.zoom - adjusted_w / 2; -	double adjusted_y = (pos.y - cam.y) * cam.zoom - adjusted_h / 2; +	width *= img_scale * cam.zoom; +	height *= img_scale * cam.zoom;  	return SDL_Rect{ -		.x = static_cast<int>(adjusted_x), -		.y = static_cast<int>(adjusted_y), -		.w = static_cast<int>(adjusted_w), -		.h = static_cast<int>(adjusted_h), +		.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_particle(const Sprite & sprite, const vec2 & pos, const double & angle, -							   const double & scale, const Camera & camera) { +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)); +		= (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * ctx.sprite.flip.flip_x) +							  | (SDL_FLIP_VERTICAL * ctx.sprite.flip.flip_y)); -	SDL_Rect srcrect = this->get_src_rect(sprite); -	SDL_Rect dstrect = this->get_dst_rect(sprite, pos, scale, camera); +	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, angle, NULL, render_flip); +	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);  } -void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { +void SDLContext::set_camera(const Camera & cam) { -	SDL_RendererFlip render_flip -		= (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) -							  | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); +	// 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); +	} -	SDL_Rect srcrect = this->get_src_rect(sprite); -	SDL_Rect dstrect = this->get_dst_rect(sprite, transform.position, transform.scale, cam); +	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_RenderCopyEx(this->game_renderer.get(), sprite.sprite_image->texture.get(), &srcrect, -					 &dstrect, transform.rotation, NULL, render_flip); -} - -void SDLContext::set_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) - (this->viewport.w / 2); -	this->viewport.y = static_cast<int>(cam.y) - (this->viewport.h / 2); +	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(); } @@ -298,76 +325,14 @@ SDLContext::texture_from_path(const std::string & path) {  	std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> img_texture;  	img_texture = {tmp_texture, [](SDL_Texture * texture) { SDL_DestroyTexture(texture); }}; +	SDL_SetTextureBlendMode(img_texture.get(), SDL_BLENDMODE_BLEND);  	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; + +ivec2 SDLContext::get_size(const Texture & ctx) { +	ivec2 size; +	SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &size.x, &size.y); +	return size;  }  void SDLContext::delay(int ms) const { SDL_Delay(ms); } - -std::vector<SDLContext::EventData> SDLContext::get_events() { -	std::vector<SDLContext::EventData> event_list; -	SDL_Event event; -	while (SDL_PollEvent(&event)) { -		switch (event.type) { -			case SDL_QUIT: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::SHUTDOWN, -				}); -				break; -			case SDL_KEYDOWN: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::KEYDOWN, -					.key = sdl_to_keycode(event.key.keysym.scancode), -					.key_repeat = (event.key.repeat != 0), -				}); -				break; -			case SDL_KEYUP: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::KEYUP, -					.key = sdl_to_keycode(event.key.keysym.scancode), -				}); -				break; -			case SDL_MOUSEBUTTONDOWN: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEDOWN, -					.mouse_button = sdl_to_mousebutton(event.button.button), -					.mouse_position = {event.button.x, event.button.y}, -				}); -				break; -			case SDL_MOUSEBUTTONUP: { -				int x, y; -				SDL_GetMouseState(&x, &y); -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEUP, -					.mouse_button = sdl_to_mousebutton(event.button.button), -					.mouse_position = {event.button.x, event.button.y}, -				}); -			} break; - -			case SDL_MOUSEMOTION: { -				event_list.push_back( -					EventData{.event_type = SDLContext::EventType::MOUSEMOVE, -							  .mouse_position = {event.motion.x, event.motion.y}, -							  .rel_mouse_move = {event.motion.xrel, event.motion.yrel}}); -			} break; - -			case SDL_MOUSEWHEEL: { -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEWHEEL, -					.mouse_position = {event.motion.x, event.motion.y}, -					.wheel_delta = event.wheel.y, -				}); -			} break; -		} -	} -	return event_list; -} diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 546e3fe..a56232f 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -16,7 +16,9 @@  #include "api/KeyCodes.h"  #include "api/Sprite.h"  #include "api/Transform.h" - +#include "api/Camera.h" +#include "api/Color.h" +#include "api/Texture.h"  #include "types.h"  namespace crepe { @@ -31,6 +33,15 @@ class InputSystem;   * event handling, and rendering to the screen. It is never used directly by the user   */  class SDLContext { +public: +	struct RenderContext { +		const Sprite & sprite; +		const Camera & cam; +		const vec2 & cam_pos; +		const vec2 & pos; +		const double & angle; +		const double & scale; +	};  public:  	//! EventType enum for passing eventType @@ -147,18 +158,11 @@ private:  	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. +	 * \brief Gets the size of a texture.  	 * \param texture Reference to the Texture object. -	 * \return Height of the texture as an integer. +	 * \return Width and height of the texture as an integer.  	 */ -	int get_height(const Texture &) const; +	ivec2 get_size(const Texture & ctx);  private:  	//! Will use draw,clear_screen, present_screen, camera. @@ -166,14 +170,9 @@ private:  	/**  	 * \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. +	 * \param RenderCtx Reference to rendering data to draw  	 */ -	void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); - -	void draw_particle(const Sprite & sprite, const vec2 & pos, const double & angle, -					   const double & scale, const Camera & camera); +	void draw(const RenderContext & ctx);  	//! Clears the screen, preparing for a new frame.  	void clear_screen(); @@ -195,18 +194,26 @@ private:  	 * \return sdl rectangle to draw a src image  	 */  	SDL_Rect get_src_rect(const Sprite & sprite) const; +  	/** -	 * \brief calculates the sqaure size of the image for an destination +	 * \brief calculates the sqaure size of the image for destination  	 * -	 * \param sprite Reference to the sprite to calculate the rectangle -	 * \param pos the pos in pixel positions -	 * \param scale the multiplier to increase of decrease for the specified sprite  -	 * \param cam Reference to the current camera in the scene to calculate the position based -	 * on the camera  +	 * \param sprite Reference to the sprite to calculate rectangle +	 * \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   	 * \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 double & scale, -						  const Camera & cam) const; +	SDL_Rect get_dst_rect(const Sprite & sprite, const vec2 & pos, const Camera & cam, +						  const vec2 & cam_pos, const double & img_scale) const; +	/** +	 * \brief Set an additional color value multiplied into render copy operations. +	 * +	 * \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);  private:  	//! sdl Window @@ -214,9 +221,6 @@ private:  	//! 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 diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 676e485..4c40940 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -15,10 +15,10 @@ void AnimatorSystem::update() {  	uint64_t tick = SDLContext::get_instance().get_ticks();  	for (Animator & a : animations) { -		if (a.active) { -			a.curr_row = (tick / 100) % a.row; -			a.animator_rect.x = (a.curr_row * a.animator_rect.w) + a.curr_col; -			a.spritesheet.sprite_rect = a.animator_rect; -		} +		if (!a.active) continue; +		// (10 frames per second) +		a.curr_row = (tick / 100) % a.row; +		a.spritesheet.mask.x = (a.curr_row * a.spritesheet.mask.w) + a.curr_col; +		a.spritesheet.mask = a.spritesheet.mask;  	}  } diff --git a/src/crepe/system/AnimatorSystem.h b/src/crepe/system/AnimatorSystem.h index 56cc7b3..f8179a9 100644 --- a/src/crepe/system/AnimatorSystem.h +++ b/src/crepe/system/AnimatorSystem.h @@ -21,12 +21,11 @@ public:  	/**  	 * \brief Updates the Animator components.  	 * -	 * This method is called periodically (likely every frame) to update the state of all +	 * This method is called to update the state of all  	 * Animator components, moving the animations forward and managing their behavior (e.g.,  	 * looping).  	 */  	void update() override; -	// FIXME: never say "likely" in the documentation lmao  };  } // namespace crepe diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index ad510f5..11c9669 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -2,15 +2,14 @@  #include <cassert>  #include <cmath>  #include <functional> -#include <iostream>  #include <stdexcept>  #include <vector>  #include "../ComponentManager.h" +#include "../api/Camera.h"  #include "../api/ParticleEmitter.h"  #include "../api/Sprite.h"  #include "../api/Transform.h" -#include "../api/Vector2.h"  #include "../facade/SDLContext.h"  #include "RenderSystem.h" @@ -21,7 +20,8 @@ using namespace std;  void RenderSystem::clear_screen() { this->context.clear_screen(); }  void RenderSystem::present_screen() { this->context.present_screen(); } -void RenderSystem::update_camera() { + +const Camera & RenderSystem::update_camera() {  	ComponentManager & mgr = this->component_manager;  	RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); @@ -30,9 +30,13 @@ void RenderSystem::update_camera() {  	for (Camera & cam : cameras) {  		if (!cam.active) continue; +		const Transform & transform +			= mgr.get_components_by_id<Transform>(cam.game_object_id).front().get();  		this->context.set_camera(cam); -		this->curr_cam_ref = &cam; +		this->cam_pos = transform.position + cam.offset; +		return cam;  	} +	throw std::runtime_error("No active cameras in current scene");  }  bool sorting_comparison(const Sprite & a, const Sprite & b) { @@ -51,12 +55,12 @@ RefVector<Sprite> RenderSystem::sort(RefVector<Sprite> & objs) const {  void RenderSystem::update() {  	this->clear_screen(); -	this->update_camera();  	this->render();  	this->present_screen();  } -bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) { +bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam, +								   const double & scale) {  	ComponentManager & mgr = this->component_manager; @@ -66,25 +70,41 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale)  	bool rendering_particles = false;  	for (const ParticleEmitter & em : emitters) { -		if (!(&em.data.sprite == &sprite)) continue; +		if (&em.data.sprite != &sprite) continue;  		rendering_particles = true;  		if (!em.active) continue;  		for (const Particle & p : em.data.particles) {  			if (!p.active) continue; -			this->context.draw_particle(sprite, p.position, p.angle, scale, -										*this->curr_cam_ref); + +			this->context.draw(SDLContext::RenderContext{ +				.sprite = sprite, +				.cam = cam, +				.cam_pos = this->cam_pos, +				.pos = p.position, +				.angle = p.angle, +				.scale = scale, +			});  		}  	}  	return rendering_particles;  } -void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { -	this->context.draw(sprite, tm, *this->curr_cam_ref); +void RenderSystem::render_normal(const Sprite & sprite, const Camera & cam, +								 const Transform & tm) { +	this->context.draw(SDLContext::RenderContext{ +		.sprite = sprite, +		.cam = cam, +		.cam_pos = this->cam_pos, +		.pos = tm.position, +		.angle = tm.rotation, +		.scale = tm.scale, +	});  }  void RenderSystem::render() { -  	ComponentManager & mgr = this->component_manager; +	const Camera & cam = this->update_camera(); +  	RefVector<Sprite> sprites = mgr.get_components_by_type<Sprite>();  	RefVector<Sprite> sorted_sprites = this->sort(sprites); @@ -93,10 +113,10 @@ void RenderSystem::render() {  		const Transform & transform  			= mgr.get_components_by_id<Transform>(sprite.game_object_id).front().get(); -		bool rendered_particles = this->render_particle(sprite, transform.scale); +		bool rendered_particles = this->render_particle(sprite, cam, transform.scale);  		if (rendered_particles) continue; -		this->render_normal(sprite, transform); +		this->render_normal(sprite, cam, transform);  	}  } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 30b41cf..096d058 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -1,17 +1,17 @@  #pragma once -#include <functional> -#include <vector> +#include <cmath>  #include "facade/SDLContext.h"  #include "System.h" -#include <cmath> +#include "types.h"  namespace crepe {  class Camera;  class Sprite; +class Transform;  /**   * \class RenderSystem @@ -37,7 +37,7 @@ private:  	void present_screen();  	//! Updates the active camera used for rendering. -	void update_camera(); +	const Camera & update_camera();  	//! Renders the whole screen  	void render(); @@ -46,10 +46,13 @@ private:  	 * \brief Renders all the particles on the screen from a given sprite.  	 *  	 * \param sprite renders the particles with given texture -	 * \param tm the Transform component for scale +	 * \param tm the Transform component for scale. This is not a const reference because each +	 *  particle has a position and rotation that needs to overwrite the transform position and +	 *  rotation without overwriting the current transform. and because the transform +	 *  constructor is now protected i cannot make tmp inside  	 * \return true if particles have been rendered  	 */ -	bool render_particle(const Sprite & sprite, const double & scale); +	bool render_particle(const Sprite & sprite, const Camera & cam, const double & scale);  	/**  	 * \brief renders a sprite with a Transform component on the screen  @@ -57,7 +60,7 @@ private:  	 * \param sprite  the sprite component that holds all the data  	 * \param tm the Transform component that holds the position,rotation and scale   	 */ -	void render_normal(const Sprite & sprite, const Transform & tm); +	void render_normal(const Sprite & sprite, const Camera & cam, const Transform & tm);  	/**  	 * \brief sort a vector sprite objects with @@ -68,20 +71,17 @@ private:  	RefVector<Sprite> sort(RefVector<Sprite> & objs) const;  	/** -	 * \todo Include color handling for sprites.  	 * \todo Add text rendering using SDL_ttf for text components.  	 * \todo Implement a text component and a button component. -	 * \todo Ensure each sprite is checked for active status before rendering. -	 * \todo Sort all layers by order before rendering.  	 * \todo Consider adding text input functionality.  	 */  private: -	//! Pointer to the current active camera for rendering -	Camera * curr_cam_ref = nullptr; -	// TODO: needs a better solution - +	// FIXME: retrieve sdlcontext via mediator after #PR57  	SDLContext & context = SDLContext::get_instance(); + +	//! camera postion in the current scene +	vec2 cam_pos;  };  } // namespace crepe diff --git a/src/crepe/types.h b/src/crepe/types.h index 17f1619..69cc526 100644 --- a/src/crepe/types.h +++ b/src/crepe/types.h @@ -27,4 +27,4 @@ typedef Vector2<float> vec2;  //! Default Vector2<double> type  typedef Vector2<double> dvec2; -} // namespace crepe +}; // namespace crepe diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index b38e860..349d11e 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -1,6 +1,7 @@ +#include "api/Animator.h"  #include "api/Camera.h" +#include "system/AnimatorSystem.h"  #include "system/ParticleSystem.h" -#include "types.h"  #include <SDL2/SDL_timer.h>  #include <crepe/ComponentManager.h> @@ -12,28 +13,31 @@  #include <crepe/api/Sprite.h>  #include <crepe/api/Texture.h>  #include <crepe/api/Transform.h> -#include <crepe/api/Vector2.h>  #include <crepe/system/RenderSystem.h> +#include <crepe/types.h>  #include <chrono> -#include <iostream> -#include <memory>  using namespace crepe;  using namespace std;  int main(int argc, char * argv[]) {  	ComponentManager mgr; -	GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0.1); +	GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 1);  	RenderSystem sys{mgr};  	ParticleSystem psys{mgr}; +	AnimatorSystem asys{mgr}; -	Color color(255, 255, 255, 255); +	Color color(255, 255, 255, 100); +	auto img = Texture("asset/texture/test_ap43.png");  	Sprite & test_sprite = game_object.add_component<Sprite>( -		make_shared<Texture>("asset/texture/img.png"), color, FlipSettings{false, false}); -	test_sprite.order_in_layer = 5; +		img, color, Sprite::FlipSettings{true, true}, 1, 1, 500); +	//game_object.add_component<Animator>(test_sprite, 4, 1, 0).active = true; +	game_object.add_component<Animator>(test_sprite, 1, 1, 0).active = true; + +	/*  	auto & test = game_object.add_component<ParticleEmitter>(ParticleEmitter::Data{  		.position = {0, 0},  		.max_particles = 10, @@ -53,17 +57,24 @@ int main(int argc, char * argv[]) {  		},  		.sprite = test_sprite,  	}); -	game_object.add_component<Camera>(Color::WHITE); +	*/ + +	auto & cam = game_object.add_component<Camera>(Color::RED, ivec2{1080, 720}, +												   vec2{2000, 2000}, 1.0f); +	/*  	game_object  		.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), color, +		.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), color,  							   FlipSettings{false, false})  		.order_in_layer  		= 6; +	*/  	auto start = std::chrono::steady_clock::now();  	while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) {  		psys.update(); +		asys.update();  		sys.update();  		SDL_Delay(10);  	} diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 8b81e74..976f9a1 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -1,4 +1,4 @@ -#include "api/Vector2.h" +#include "api/Texture.h"  #include <crepe/ComponentManager.h>  #include <crepe/Particle.h>  #include <crepe/api/Config.h> @@ -28,9 +28,9 @@ public:  			GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0);  			Color color(0, 0, 0, 0); +			auto s1 = Texture("asset/texture/img.png");  			Sprite & test_sprite = game_object.add_component<Sprite>( -				make_shared<Texture>("asset/texture/img.png"), color, -				FlipSettings{true, true}); +				s1, color, Sprite::FlipSettings{true, true}, 1, 1, 100);  			game_object.add_component<ParticleEmitter>(ParticleEmitter::Data{  				.position = {0, 0}, diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp index f37fb56..bb5b81a 100644 --- a/src/test/RenderSystemTest.cpp +++ b/src/test/RenderSystemTest.cpp @@ -1,4 +1,4 @@ -#include "api/Camera.h" +#include "types.h"  #include <functional>  #include <gtest/gtest.h>  #include <memory> @@ -7,6 +7,7 @@  #define private public  #define protected public +#include "crepe/api/Camera.h"  #include <crepe/ComponentManager.h>  #include <crepe/api/Color.h>  #include <crepe/api/GameObject.h> @@ -29,40 +30,30 @@ public:  	GameObject entity4 = this->mgr.new_object("name");  	void SetUp() override { -		auto & sprite1 -			= entity1.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), -											Color(0, 0, 0, 0), FlipSettings{false, false}); -		ASSERT_NE(sprite1.sprite_image.get(), nullptr); -		sprite1.order_in_layer = 5; -		sprite1.sorting_in_layer = 5; +		auto s1 = Texture("asset/texture/img.png"); +		auto s2 = Texture("asset/texture/img.png"); +		auto s3 = Texture("asset/texture/img.png"); +		auto s4 = Texture("asset/texture/img.png"); +		auto & sprite1 = entity1.add_component<Sprite>( +			s1, Color(0, 0, 0, 0), Sprite::FlipSettings{false, false}, 5, 5, 100); +		ASSERT_NE(sprite1.sprite_image.texture.get(), nullptr);  		EXPECT_EQ(sprite1.order_in_layer, 5);  		EXPECT_EQ(sprite1.sorting_in_layer, 5); -		auto & sprite2 -			= entity2.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), -											Color(0, 0, 0, 0), FlipSettings{false, false}); -		ASSERT_NE(sprite2.sprite_image.get(), nullptr); -		sprite2.sorting_in_layer = 2; -		sprite2.order_in_layer = 1; - +		auto & sprite2 = entity2.add_component<Sprite>( +			s2, Color(0, 0, 0, 0), Sprite::FlipSettings{false, false}, 2, 1, 100); +		ASSERT_NE(sprite2.sprite_image.texture.get(), nullptr);  		EXPECT_EQ(sprite2.sorting_in_layer, 2);  		EXPECT_EQ(sprite2.order_in_layer, 1); -		auto & sprite3 -			= entity3.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), -											Color(0, 0, 0, 0), FlipSettings{false, false}); -		ASSERT_NE(sprite3.sprite_image.get(), nullptr); -		sprite3.sorting_in_layer = 1; -		sprite3.order_in_layer = 2; - +		auto & sprite3 = entity3.add_component<Sprite>( +			s3, Color(0, 0, 0, 0), Sprite::FlipSettings{false, false}, 1, 2, 100); +		ASSERT_NE(sprite3.sprite_image.texture.get(), nullptr);  		EXPECT_EQ(sprite3.sorting_in_layer, 1);  		EXPECT_EQ(sprite3.order_in_layer, 2); -		auto & sprite4 -			= entity4.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), -											Color(0, 0, 0, 0), FlipSettings{false, false}); -		ASSERT_NE(sprite4.sprite_image.get(), nullptr); -		sprite4.sorting_in_layer = 1; -		sprite4.order_in_layer = 1; +		auto & sprite4 = entity4.add_component<Sprite>( +			s4, Color(0, 0, 0, 0), Sprite::FlipSettings{false, false}, 1, 1, 100); +		ASSERT_NE(sprite4.sprite_image.texture.get(), nullptr);  		EXPECT_EQ(sprite4.sorting_in_layer, 1);  		EXPECT_EQ(sprite4.order_in_layer, 1);  	} @@ -73,8 +64,9 @@ TEST_F(RenderSystemTest, expected_throws) {  	// no texture img  	EXPECT_ANY_THROW({ -		entity1.add_component<Sprite>(make_shared<Texture>("NO_IMAGE"), Color(0, 0, 0, 0), -									  FlipSettings{false, false}); +		auto test = Texture(""); +		entity1.add_component<Sprite>(test, Color(0, 0, 0, 0), +									  Sprite::FlipSettings{false, false}, 1, 1, 100);  	});  	// No camera @@ -121,7 +113,7 @@ TEST_F(RenderSystemTest, sorting_sprites) {  }  TEST_F(RenderSystemTest, Update) { -	entity1.add_component<Camera>(Color::WHITE); +	entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);  	{  		vector<reference_wrapper<Sprite>> sprites = this->mgr.get_components_by_type<Sprite>();  		ASSERT_EQ(sprites.size(), 4); @@ -149,7 +141,7 @@ TEST_F(RenderSystemTest, Camera) {  		EXPECT_NE(cameras.size(), 1);  	}  	{ -		entity1.add_component<Camera>(Color::WHITE); +		entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);  		auto cameras = this->mgr.get_components_by_type<Camera>();  		EXPECT_EQ(cameras.size(), 1);  	} @@ -157,9 +149,9 @@ TEST_F(RenderSystemTest, Camera) {  	//TODO improve with newer version  }  TEST_F(RenderSystemTest, Color) { -	entity1.add_component<Camera>(Color::WHITE); +	entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);  	auto & sprite = this->mgr.get_components_by_id<Sprite>(entity1.id).front().get(); -	ASSERT_NE(sprite.sprite_image.get(), nullptr); +	ASSERT_NE(sprite.sprite_image.texture.get(), nullptr);  	sprite.color = Color::GREEN;  	EXPECT_EQ(sprite.color.r, Color::GREEN.r); |