aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/crepe/api/Animator.cpp48
-rw-r--r--src/crepe/api/Animator.h101
-rw-r--r--src/crepe/api/Camera.cpp9
-rw-r--r--src/crepe/api/Camera.h26
-rw-r--r--src/crepe/api/Config.h2
-rw-r--r--src/crepe/api/LoopManager.cpp1
-rw-r--r--src/crepe/api/Sprite.cpp16
-rw-r--r--src/crepe/api/Sprite.h82
-rw-r--r--src/crepe/api/Transform.h2
-rw-r--r--src/crepe/facade/SDLContext.cpp117
-rw-r--r--src/crepe/facade/SDLContext.h29
-rw-r--r--src/crepe/system/AnimatorSystem.cpp27
-rw-r--r--src/crepe/system/AnimatorSystem.h7
-rw-r--r--src/crepe/system/RenderSystem.cpp21
-rw-r--r--src/crepe/system/RenderSystem.h11
-rw-r--r--src/example/rendering_particle.cpp73
-rw-r--r--src/test/ParticleTest.cpp6
-rw-r--r--src/test/RenderSystemTest.cpp132
18 files changed, 457 insertions, 253 deletions
diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp
index 45f67f6..dc99fd4 100644
--- a/src/crepe/api/Animator.cpp
+++ b/src/crepe/api/Animator.cpp
@@ -7,21 +7,53 @@
using namespace crepe;
-Animator::Animator(game_object_id_t id, Sprite & ss, int row, int col, int col_animator)
+Animator::Animator(uint32_t id, Sprite & ss, int max_row, int max_col,
+ const Animator::Data & ctx)
: Component(id),
spritesheet(ss),
- row(row),
- col(col) {
+ row(max_row),
+ col(max_col),
+ data(ctx) {
dbg_trace();
- 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;
+ this->spritesheet.mask.h /= this->col;
+ this->spritesheet.mask.w /= this->row;
+ this->spritesheet.mask.x = this->data.curr_row * this->spritesheet.mask.w;
+ this->spritesheet.mask.y = this->data.curr_col * this->spritesheet.mask.h;
// 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(); }
+
+void Animator::loop() { this->data.looping = true; }
+
+void Animator::play() { this->active = true; }
+
+void Animator::pause() { this->active = false; }
+
+void Animator::stop() {
+ this->active = false;
+ this->data.curr_col = 0;
+ this->data.curr_row = 0;
+}
+void Animator::set_fps(int fps) { this->data.fps = fps; }
+
+void Animator::set_cycle_range(int start, int end) {
+ this->data.cycle_start = start, this->data.cycle_end = end;
+}
+
+void Animator::set_anim(int col) {
+ Animator::Data & ctx = this->data;
+ this->spritesheet.mask.x = ctx.curr_row = 0;
+ ctx.curr_col = col;
+ this->spritesheet.mask.y = ctx.curr_col * this->spritesheet.mask.h;
+}
+
+void Animator::next_anim() {
+ Animator::Data & ctx = this->data;
+ ctx.curr_row = ctx.curr_row++ % this->row;
+ this->spritesheet.mask.x = ctx.curr_row * this->spritesheet.mask.w;
+}
diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h
index 6c506aa..dab6697 100644
--- a/src/crepe/api/Animator.h
+++ b/src/crepe/api/Animator.h
@@ -16,33 +16,100 @@ class SDLContext;
* sheet. It can be used to play animations, loop them, or stop them.
*/
class Animator : public Component {
+public:
+ struct Data {
+
+ //! frames per second for animation
+ int fps = 1;
+
+ //! The current col being animated.
+ int curr_col = 0;
+
+ //! The current row being animated.
+ int curr_row = 0;
+
+ //! should the animation loop
+ bool looping = false;
+
+ //! starting frame for cycling
+ int cycle_start = 0;
+
+ //! end frame for cycling (-1 --> use last frame)
+ int cycle_end = -1;
+
+ //! offset in pixels.
+ // TODO implement
+ int offset_x = 0;
+ };
public:
- //TODO: need to implement this
+ /**
+ * \brief Animator will repeat the animation
+ *
+ */
void loop();
+
+ /**
+ * \brief starts the animation
+ *
+ */
+ void play();
+ /**
+ * \brief pauses the animation
+ *
+ * sets the active false
+ *
+ */
+ void pause();
+
+ /**
+ * \brief stops the animation
+ *
+ * sets the active on false and resets all the current rows and columns
+ *
+ */
void stop();
+ /**
+ * \brief set frames per second
+ *
+ * \param fps frames per second
+ */
+ void set_fps(int fps);
+ /**
+ * \brief set the range in the row
+ *
+ * \param start of row animation
+ * \param end of row animation
+ */
+ void set_cycle_range(int start, int end);
+ /**
+ * \brief select which column to animate from
+ *
+ * \param col animation column
+ */
+ void set_anim(int col);
+
+ /**
+ * \brief will go to the next animaiton of current row
+ *
+ */
+ void next_anim();
public:
/**
* \brief Constructs an Animator object that will control animations for a sprite sheet.
*
* \param id The unique identifier for the component, typically assigned automatically.
- * \param spritesheet A reference to the Sprite object which holds the sprite sheet for
- * animation.
- * \param row The maximum number of rows in the sprite sheet.
- * \param col The maximum number of columns in the sprite sheet.
- * \param col_animate The specific col index of the sprite sheet to animate. This allows
- * selecting which col to animate from multiple col in the sheet.
+ * \param ctx animator data
*
* This constructor sets up the Animator with the given parameters, and initializes the
* animation system.
*/
- Animator(uint32_t id, Sprite & spritesheet, int row, int col, int col_animate);
-
+ Animator(uint32_t id, Sprite & ss, int max_row, int max_col, const Animator::Data & ctx);
~Animator(); // dbg_trace
-private:
- //! A reference to the Sprite sheet containing the animation frames.
+public:
+ //! A reference to the Sprite sheet containing.
Sprite & spritesheet;
//! The maximum number of columns in the sprite sheet.
@@ -51,21 +118,11 @@ private:
//! The maximum number of rows in the sprite sheet.
const int row;
- //! The current col being animated.
- int curr_col = 0;
-
- //! The current row being animated.
- int curr_row = 0;
-
- //TODO: Is this necessary?
- //int fps;
+ Animator::Data data;
private:
//! AnimatorSystem adjust the private member parameters of Animator;
friend class AnimatorSystem;
-
- //! SDLContext reads the Animator member var's
- friend class SDLContext;
};
} // namespace crepe
//
diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp
index 39d8ab0..b042c35 100644
--- a/src/crepe/api/Camera.cpp
+++ b/src/crepe/api/Camera.cpp
@@ -2,19 +2,16 @@
#include "util/Log.h"
#include "Camera.h"
-#include "Color.h"
#include "Component.h"
using namespace crepe;
-Camera::Camera(game_object_id_t id, const Color & bg_color, const ivec2 & screen,
- const vec2 & viewport_size, const double & zoom, const vec2 & offset)
+Camera::Camera(game_object_id_t id, const ivec2 & screen, const vec2 & viewport_size,
+ const Data & ctx)
: Component(id),
- bg_color(bg_color),
- offset(offset),
screen(screen),
viewport_size(viewport_size),
- zoom(zoom) {
+ data(ctx) {
dbg_trace();
}
diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h
index 2d8fa48..f626379 100644
--- a/src/crepe/api/Camera.h
+++ b/src/crepe/api/Camera.h
@@ -14,23 +14,30 @@ namespace crepe {
* position, and zoom level. It controls what part of the game world is visible on the screen.
*/
class Camera : public Component {
+public:
+ struct Data {
+ //! Background color of the camera view.
+ const Color bg_color = Color::WHITE;
+
+ //! Zoom level of the camera view.
+ double zoom = 1;
+
+ //! offset postion from the game object transform component
+ vec2 offset;
+ };
public:
/**
* \brief Constructs a Camera with the specified ID and background color.
* \param id Unique identifier for the camera component.
- * \param bg_color Background color for the camera view.
+ * \param ctx the camera component data
*/
- 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(game_object_id_t id, const ivec2 & screen, const vec2 & viewport_size,
+ const Data & ctx);
~Camera(); // dbg_trace only
public:
- //! Background color of the camera view.
- const Color bg_color;
-
- //! offset postion from the game object transform component
- vec2 offset;
+ Camera::Data data;
//! screen the display size in pixels ( output resolution )
const ivec2 screen;
@@ -38,9 +45,6 @@ public:
//! viewport is the area of the world visible through the camera (in world units)
const vec2 viewport_size;
- //! Zoom level of the camera view.
- const double zoom;
-
public:
/**
* \brief Gets the maximum number of camera instances allowed.
diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h
index 225e9b9..200a3b0 100644
--- a/src/crepe/api/Config.h
+++ b/src/crepe/api/Config.h
@@ -67,7 +67,7 @@ public:
//! default window settings
struct {
//TODO make this constexpr because this will never change
- ivec2 default_size = {1080, 720};
+ ivec2 default_size = {1280, 720};
std::string window_title = "Jetpack joyride clone";
} window_settings;
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
index dc2d9e0..3e9a88e 100644
--- a/src/crepe/api/LoopManager.cpp
+++ b/src/crepe/api/LoopManager.cpp
@@ -60,6 +60,7 @@ void LoopManager::setup() {
this->game_running = true;
timer.start();
timer.set_fps(200);
+ this->scene_manager.load_next_scene();
}
void LoopManager::render() {
diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp
index 0a2ad4c..b52a344 100644
--- a/src/crepe/api/Sprite.cpp
+++ b/src/crepe/api/Sprite.cpp
@@ -6,24 +6,20 @@
#include "Component.h"
#include "Sprite.h"
#include "Texture.h"
+#include "types.h"
using namespace std;
using namespace crepe;
-Sprite::Sprite(game_object_id_t id, Texture & image, const Color & color,
- const FlipSettings & flip, int sort_layer, int order_layer, int height)
+Sprite::Sprite(game_object_id_t id, Texture & texture, const Sprite::Data & ctx)
: Component(id),
- color(color),
- flip(flip),
- sprite_image(std::move(image)),
- sorting_in_layer(sort_layer),
- order_in_layer(order_layer),
- height(height) {
+ texture(std::move(texture)),
+ data(ctx) {
dbg_trace();
- this->mask.w = sprite_image.get_size().x;
- this->mask.h = sprite_image.get_size().y;
+ this->mask.w = this->texture.get_size().x;
+ this->mask.h = this->texture.get_size().y;
this->aspect_ratio = static_cast<double>(this->mask.w) / this->mask.h;
}
diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h
index a0e90a0..a1230db 100644
--- a/src/crepe/api/Sprite.h
+++ b/src/crepe/api/Sprite.h
@@ -1,11 +1,10 @@
#pragma once
-#include <cstdint>
-
#include "../Component.h"
#include "Color.h"
#include "Texture.h"
+#include "types.h"
namespace crepe {
@@ -20,60 +19,67 @@ class AnimatorSystem;
* flip settings, and is managed in layers with defined sorting orders.
*/
class Sprite : public Component {
-
public:
struct FlipSettings {
bool flip_x = false;
bool flip_y = false;
};
+ struct Data {
+ //! Color tint of the sprite
+ Color color = Color::WHITE;
+
+ //! Flip settings for the sprite
+ FlipSettings flip;
+
+ //! Layer sorting level of the sprite
+ const int sorting_in_layer = 0;
+
+ //! Order within the sorting layer
+ const int order_in_layer = 0;
+
+ /**
+ * \size width and height of the sprite in game units
+ *
+ * if height is filled in and not width it will multiply width by aspect_ratio.
+ * if width is filled in and not height it will multiply height by aspect_ratio.
+ * if neither is filled it will not show sprite because size will be zero
+ * if both are filled will it use the width and height without making sure the aspect_ratio
+ * is correct
+ */
+ vec2 size;
+
+ //! independent sprite angle. rotating clockwise direction in degrees
+ double angle_offset = 0;
+
+ //! independent sprite scale multiplier
+ double scale_offset = 1;
+ };
+
public:
- // TODO: Loek comment in github #27 will be looked another time
- // about shared_ptr Texture
/**
* \brief Constructs a Sprite with specified parameters.
* \param game_id Unique identifier for the game object this sprite belongs to.
- * \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, Texture & image, const Color & color,
- const FlipSettings & flip, int sort_layer, int order_layer, int height);
-
- /**
- * \brief Destroys the Sprite instance.
+ * \param texture asset of the image
+ * \param ctx all the sprite data
*/
+ Sprite(game_object_id_t id, Texture & texture, const Data & ctx);
~Sprite();
//! Texture used for the sprite
- const Texture sprite_image;
-
- //! Color tint of the sprite
- Color color;
-
- //! Flip settings for the sprite
- FlipSettings flip;
+ const Texture texture;
- //! Layer sorting level of the sprite
- const int sorting_in_layer;
- //! Order within the sorting layer
- const int order_in_layer;
-
- //! height in world units
- const int height;
+ Data data;
+private:
/**
- * \aspect_ratio ratio of the img so that scaling will not become weird
- *
- * cannot be const because if Animator component is addded then ratio becomes scuffed and
- * does it need to be calculated again in the Animator
- */
- double aspect_ratio;
+ * \aspect_ratio ratio of the img so that scaling will not become weird
+ *
+ * cannot be const because if Animator component is addded then ratio becomes scuffed and
+ * does it need to be calculated again in the Animator
+ */
+ float aspect_ratio;
-private:
//! Reads the mask of sprite
friend class SDLContext;
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index 6243a93..34ac70a 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -15,7 +15,7 @@ class Transform : public Component {
public:
//! Translation (shift)
vec2 position = {0, 0};
- //! Rotation, in degrees
+ //! Rotation, in degrees clockwise
double rotation = 0;
//! Multiplication factor
double scale = 0;
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp
index ad9f1f0..72b4e42 100644
--- a/src/crepe/facade/SDLContext.cpp
+++ b/src/crepe/facade/SDLContext.cpp
@@ -215,11 +215,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 +231,57 @@ 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 DstRect & 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 = {data.size.x == 0 && data.size.y != 0 ? data.size.y * ctx.sprite.aspect_ratio
+ : data.size.x,
+ data.size.y == 0 && data.size.x != 0 ? data.size.x / ctx.sprite.aspect_ratio
+ : data.size.y};
+
+ const CameraValues & cam = ctx.cam;
+
+ size *= cam.render_scale * ctx.img_scale * data.scale_offset;
+
+ vec2 screen_pos = (ctx.pos - 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);
+ SDL_FRect dstrect = this->get_dst_rect(SDLContext::DstRect{
+ .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.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_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 +289,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;
+ double screen_aspect = static_cast<double>(cam.screen.x) / cam.screen.y;
+ double 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..dfdaa56 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -33,10 +33,17 @@ class InputSystem;
*/
class SDLContext {
public:
+ //! data that the camera component cannot hold
+ struct CameraValues {
+ vec2 zoomed_viewport;
+ vec2 render_scale;
+ vec2 bar_size;
+ vec2 cam_pos;
+ };
+
struct RenderContext {
const Sprite & sprite;
- const Camera & cam;
- const vec2 & cam_pos;
+ const CameraValues & cam;
const vec2 & pos;
const double & angle;
const double & scale;
@@ -114,8 +121,6 @@ private:
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 +175,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 +189,15 @@ 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:
+ struct DstRect {
+ const Sprite & sprite;
+ const CameraValues & cam;
+ const vec2 & pos;
+ const double & img_scale;
+ };
/**
* \brief calculates the sqaure size of the image
*
@@ -205,8 +216,7 @@ private:
* \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 DstRect & ctx) const;
/**
* \brief Set an additional color value multiplied into render copy operations.
*
@@ -221,6 +231,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/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp
index 8bb6465..9aede7f 100644
--- a/src/crepe/system/AnimatorSystem.cpp
+++ b/src/crepe/system/AnimatorSystem.cpp
@@ -1,4 +1,4 @@
-#include <cstdint>
+
#include "../api/Animator.h"
#include "../facade/SDLContext.h"
@@ -13,12 +13,27 @@ void AnimatorSystem::update() {
RefVector<Animator> animations = mgr.get_components_by_type<Animator>();
- uint64_t tick = SDLContext::get_instance().get_ticks();
+ double elapsed_time = this->timer.get_current_time();
+
for (Animator & a : animations) {
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;
+
+ Animator::Data & ctx = a.data;
+ double frame_duration = 1.0f / ctx.fps;
+
+ int last_frame = ctx.curr_row;
+
+ int cycle_end = (ctx.cycle_end == -1) ? a.row : ctx.cycle_end;
+ int total_frames = cycle_end - ctx.cycle_start;
+
+ int curr_frame = static_cast<int>(elapsed_time / frame_duration) % total_frames;
+
+ ctx.curr_row = ctx.cycle_start + curr_frame;
+ a.spritesheet.mask.x = ctx.curr_row * a.spritesheet.mask.w;
+ a.spritesheet.mask.y = (ctx.curr_col * a.spritesheet.mask.h);
+
+ if (!ctx.looping && curr_frame == ctx.cycle_start && last_frame == total_frames - 1) {
+ a.active = false;
+ }
}
}
diff --git a/src/crepe/system/AnimatorSystem.h b/src/crepe/system/AnimatorSystem.h
index f8179a9..e8a5158 100644
--- a/src/crepe/system/AnimatorSystem.h
+++ b/src/crepe/system/AnimatorSystem.h
@@ -1,9 +1,7 @@
#pragma once
#include "System.h"
-
-//TODO:
-// control if flip works with animation system
+#include "api/LoopTimer.h"
namespace crepe {
@@ -26,6 +24,9 @@ public:
* looping).
*/
void update() override;
+
+private:
+ LoopTimer & timer = LoopTimer::get_instance();
};
} // namespace crepe
diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp
index 92dba43..111ad7d 100644
--- a/src/crepe/system/RenderSystem.cpp
+++ b/src/crepe/system/RenderSystem.cpp
@@ -21,7 +21,7 @@ void RenderSystem::clear_screen() { this->context.clear_screen(); }
void RenderSystem::present_screen() { this->context.present_screen(); }
-const Camera & RenderSystem::update_camera() {
+SDLContext::CameraValues RenderSystem::update_camera() {
ComponentManager & mgr = this->mediator.component_manager;
RefVector<Camera> cameras = mgr.get_components_by_type<Camera>();
@@ -32,16 +32,17 @@ const Camera & RenderSystem::update_camera() {
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->cam_pos = transform.position + cam.offset;
- return cam;
+ SDLContext::CameraValues cam_val = this->context.set_camera(cam);
+ cam_val.cam_pos = transform.position + cam.data.offset;
+ return cam_val;
}
throw std::runtime_error("No active cameras in current scene");
}
bool sorting_comparison(const Sprite & a, const Sprite & b) {
- if (a.sorting_in_layer < b.sorting_in_layer) return true;
- if (a.sorting_in_layer == b.sorting_in_layer) return a.order_in_layer < b.order_in_layer;
+ if (a.data.sorting_in_layer < b.data.sorting_in_layer) return true;
+ if (a.data.sorting_in_layer == b.data.sorting_in_layer)
+ return a.data.order_in_layer < b.data.order_in_layer;
return false;
}
@@ -59,7 +60,7 @@ void RenderSystem::update() {
this->present_screen();
}
-bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam,
+bool RenderSystem::render_particle(const Sprite & sprite, const SDLContext::CameraValues & cam,
const double & scale) {
ComponentManager & mgr = this->mediator.component_manager;
@@ -80,7 +81,6 @@ bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam,
this->context.draw(SDLContext::RenderContext{
.sprite = sprite,
.cam = cam,
- .cam_pos = this->cam_pos,
.pos = p.position,
.angle = p.angle,
.scale = scale,
@@ -89,12 +89,11 @@ bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam,
}
return rendering_particles;
}
-void RenderSystem::render_normal(const Sprite & sprite, const Camera & cam,
+void RenderSystem::render_normal(const Sprite & sprite, const SDLContext::CameraValues & 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,
@@ -103,7 +102,7 @@ void RenderSystem::render_normal(const Sprite & sprite, const Camera & cam,
void RenderSystem::render() {
ComponentManager & mgr = this->mediator.component_manager;
- const Camera & cam = this->update_camera();
+ const SDLContext::CameraValues & cam = this->update_camera();
RefVector<Sprite> sprites = mgr.get_components_by_type<Sprite>();
RefVector<Sprite> sorted_sprites = this->sort(sprites);
diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h
index 096d058..eaf1213 100644
--- a/src/crepe/system/RenderSystem.h
+++ b/src/crepe/system/RenderSystem.h
@@ -37,7 +37,7 @@ private:
void present_screen();
//! Updates the active camera used for rendering.
- const Camera & update_camera();
+ SDLContext::CameraValues update_camera();
//! Renders the whole screen
void render();
@@ -52,7 +52,8 @@ private:
* constructor is now protected i cannot make tmp inside
* \return true if particles have been rendered
*/
- bool render_particle(const Sprite & sprite, const Camera & cam, const double & scale);
+ bool render_particle(const Sprite & sprite, const SDLContext::CameraValues & cam,
+ const double & scale);
/**
* \brief renders a sprite with a Transform component on the screen
@@ -60,7 +61,8 @@ 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 Camera & cam, const Transform & tm);
+ void render_normal(const Sprite & sprite, const SDLContext::CameraValues & cam,
+ const Transform & tm);
/**
* \brief sort a vector sprite objects with
@@ -79,9 +81,6 @@ private:
private:
// 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/example/rendering_particle.cpp b/src/example/rendering_particle.cpp
index 349d11e..07e43a1 100644
--- a/src/example/rendering_particle.cpp
+++ b/src/example/rendering_particle.cpp
@@ -1,5 +1,7 @@
#include "api/Animator.h"
#include "api/Camera.h"
+#include "api/LoopManager.h"
+#include "api/LoopTimer.h"
#include "system/AnimatorSystem.h"
#include "system/ParticleSystem.h"
#include <SDL2/SDL_timer.h>
@@ -16,28 +18,10 @@
#include <crepe/system/RenderSystem.h>
#include <crepe/types.h>
-#include <chrono>
-
using namespace crepe;
using namespace std;
-int main(int argc, char * argv[]) {
- ComponentManager mgr;
- 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, 100);
-
- auto img = Texture("asset/texture/test_ap43.png");
- Sprite & test_sprite = game_object.add_component<Sprite>(
- 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,
@@ -59,8 +43,47 @@ int main(int argc, char * argv[]) {
});
*/
- auto & cam = game_object.add_component<Camera>(Color::RED, ivec2{1080, 720},
- vec2{2000, 2000}, 1.0f);
+class TestScene : public Scene {
+public:
+ void load_scene() {
+ ComponentManager & mgr = this->component_manager;
+ GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 1);
+
+ Color color(255, 255, 255, 255);
+
+ auto img = Texture("asset/spritesheet/pokemon_spritesheet.png");
+
+ Sprite & test_sprite = game_object.add_component<Sprite>(
+ img, Sprite::Data{
+ .color = color,
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 2,
+ .order_in_layer = 2,
+ .size = {0, 100},
+ .angle_offset = 0,
+ });
+
+ auto & anim = game_object.add_component<Animator>(test_sprite, 4, 4,
+ Animator::Data{
+ .fps = 1,
+ .looping = false,
+ });
+ anim.set_anim(2);
+ anim.active = false;
+
+ auto & cam = game_object.add_component<Camera>(ivec2{1280, 720}, vec2{400, 400},
+ Camera::Data{
+ .bg_color = Color::WHITE,
+ });
+ }
+
+ string get_name() const { return "TestScene"; };
+};
+
+int main(int argc, char * argv[]) {
+ LoopManager engine;
+ engine.add_scene<TestScene>();
+ engine.start();
/*
game_object
@@ -71,13 +94,5 @@ int main(int argc, char * argv[]) {
= 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);
- }
-
return 0;
}
diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp
index a659fe5..1409c4f 100644
--- a/src/test/ParticleTest.cpp
+++ b/src/test/ParticleTest.cpp
@@ -32,7 +32,11 @@ public:
Color color(0, 0, 0, 0);
auto s1 = Texture("asset/texture/img.png");
Sprite & test_sprite = game_object.add_component<Sprite>(
- s1, color, Sprite::FlipSettings{true, true}, 1, 1, 100);
+ s1, Sprite::Data{
+ .color = color,
+ .flip = Sprite::FlipSettings{true, true},
+ .size = {10, 10},
+ });
game_object.add_component<ParticleEmitter>(ParticleEmitter::Data{
.position = {0, 0},
diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp
index c105dcb..4868ddd 100644
--- a/src/test/RenderSystemTest.cpp
+++ b/src/test/RenderSystemTest.cpp
@@ -35,28 +35,50 @@ public:
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>(
- 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>(
- 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>(
- 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);
+ auto & sprite1
+ = entity1.add_component<Sprite>(s1, Sprite::Data{
+ .color = Color(0, 0, 0, 0),
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 5,
+ .order_in_layer = 5,
+ .size = {10, 10},
+ });
+
+ ASSERT_NE(sprite1.texture.texture.get(), nullptr);
+ EXPECT_EQ(sprite1.data.order_in_layer, 5);
+ EXPECT_EQ(sprite1.data.sorting_in_layer, 5);
+ auto & sprite2
+ = entity2.add_component<Sprite>(s2, Sprite::Data{
+ .color = Color(0, 0, 0, 0),
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 2,
+ .order_in_layer = 1,
+ });
+ ASSERT_NE(sprite2.texture.texture.get(), nullptr);
+ EXPECT_EQ(sprite2.data.sorting_in_layer, 2);
+ EXPECT_EQ(sprite2.data.order_in_layer, 1);
+
+ auto & sprite3
+ = entity3.add_component<Sprite>(s3, Sprite::Data{
+ .color = Color(0, 0, 0, 0),
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 1,
+ .order_in_layer = 2,
+ });
+ ASSERT_NE(sprite3.texture.texture.get(), nullptr);
+ EXPECT_EQ(sprite3.data.sorting_in_layer, 1);
+ EXPECT_EQ(sprite3.data.order_in_layer, 2);
+
+ auto & sprite4
+ = entity4.add_component<Sprite>(s4, Sprite::Data{
+ .color = Color(0, 0, 0, 0),
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 1,
+ .order_in_layer = 1,
+ });
+ ASSERT_NE(sprite4.texture.texture.get(), nullptr);
+ EXPECT_EQ(sprite4.data.sorting_in_layer, 1);
+ EXPECT_EQ(sprite4.data.order_in_layer, 1);
}
};
@@ -66,8 +88,13 @@ TEST_F(RenderSystemTest, expected_throws) {
// no texture img
EXPECT_ANY_THROW({
auto test = Texture("");
- entity1.add_component<Sprite>(test, Color(0, 0, 0, 0),
- Sprite::FlipSettings{false, false}, 1, 1, 100);
+ auto & sprite1 = entity1.add_component<Sprite>(
+ test, Sprite::Data{
+ .color = Color(0, 0, 0, 0),
+ .flip = Sprite::FlipSettings{false, false},
+ .sorting_in_layer = 1,
+ .order_in_layer = 1,
+ });
});
// No camera
@@ -89,32 +116,35 @@ TEST_F(RenderSystemTest, sorting_sprites) {
// 3. sorting_in_layer: 2, order_in_layer: 1 (entity2)
// 4. sorting_in_layer: 5, order_in_layer: 5 (entity1)
- EXPECT_EQ(sorted_sprites[0].get().sorting_in_layer, 1);
- EXPECT_EQ(sorted_sprites[0].get().order_in_layer, 1);
+ EXPECT_EQ(sorted_sprites[0].get().data.sorting_in_layer, 1);
+ EXPECT_EQ(sorted_sprites[0].get().data.order_in_layer, 1);
- EXPECT_EQ(sorted_sprites[1].get().sorting_in_layer, 1);
- EXPECT_EQ(sorted_sprites[1].get().order_in_layer, 2);
+ EXPECT_EQ(sorted_sprites[1].get().data.sorting_in_layer, 1);
+ EXPECT_EQ(sorted_sprites[1].get().data.order_in_layer, 2);
- EXPECT_EQ(sorted_sprites[2].get().sorting_in_layer, 2);
- EXPECT_EQ(sorted_sprites[2].get().order_in_layer, 1);
+ EXPECT_EQ(sorted_sprites[2].get().data.sorting_in_layer, 2);
+ EXPECT_EQ(sorted_sprites[2].get().data.order_in_layer, 1);
- EXPECT_EQ(sorted_sprites[3].get().sorting_in_layer, 5);
- EXPECT_EQ(sorted_sprites[3].get().order_in_layer, 5);
+ EXPECT_EQ(sorted_sprites[3].get().data.sorting_in_layer, 5);
+ EXPECT_EQ(sorted_sprites[3].get().data.order_in_layer, 5);
for (size_t i = 1; i < sorted_sprites.size(); ++i) {
const Sprite & prev = sorted_sprites[i - 1].get();
const Sprite & curr = sorted_sprites[i].get();
- if (prev.sorting_in_layer == curr.sorting_in_layer) {
- EXPECT_LE(prev.order_in_layer, curr.order_in_layer);
+ if (prev.data.sorting_in_layer == curr.data.sorting_in_layer) {
+ EXPECT_LE(prev.data.order_in_layer, curr.data.order_in_layer);
} else {
- EXPECT_LE(prev.sorting_in_layer, curr.sorting_in_layer);
+ EXPECT_LE(prev.data.sorting_in_layer, curr.data.sorting_in_layer);
}
}
}
TEST_F(RenderSystemTest, Update) {
- entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);
+ entity1.add_component<Camera>(Camera::Data{.bg_color = Color::WHITE,
+ .screen = ivec2{1080, 720},
+ .viewport_size = vec2{2000, 2000},
+ .zoom = 1.0f});
{
vector<reference_wrapper<Sprite>> sprites = this->mgr.get_components_by_type<Sprite>();
ASSERT_EQ(sprites.size(), 4);
@@ -142,7 +172,10 @@ TEST_F(RenderSystemTest, Camera) {
EXPECT_NE(cameras.size(), 1);
}
{
- entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);
+ entity1.add_component<Camera>(Camera::Data{.bg_color = Color::WHITE,
+ .screen = ivec2{1080, 720},
+ .viewport_size = vec2{2000, 2000},
+ .zoom = 1.0f});
auto cameras = this->mgr.get_components_by_type<Camera>();
EXPECT_EQ(cameras.size(), 1);
}
@@ -150,18 +183,21 @@ TEST_F(RenderSystemTest, Camera) {
//TODO improve with newer version
}
TEST_F(RenderSystemTest, Color) {
- entity1.add_component<Camera>(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, 1.0f);
+ entity1.add_component<Camera>(Camera::Data{.bg_color = Color::WHITE,
+ .screen = ivec2{1080, 720},
+ .viewport_size = vec2{2000, 2000},
+ .zoom = 1.0f});
auto & sprite = this->mgr.get_components_by_id<Sprite>(entity1.id).front().get();
- ASSERT_NE(sprite.sprite_image.texture.get(), nullptr);
+ ASSERT_NE(sprite.texture.texture.get(), nullptr);
- sprite.color = Color::GREEN;
- EXPECT_EQ(sprite.color.r, Color::GREEN.r);
- EXPECT_EQ(sprite.color.g, Color::GREEN.g);
- EXPECT_EQ(sprite.color.b, Color::GREEN.b);
- EXPECT_EQ(sprite.color.a, Color::GREEN.a);
+ sprite.data.color = Color::GREEN;
+ EXPECT_EQ(sprite.data.color.r, Color::GREEN.r);
+ EXPECT_EQ(sprite.data.color.g, Color::GREEN.g);
+ EXPECT_EQ(sprite.data.color.b, Color::GREEN.b);
+ EXPECT_EQ(sprite.data.color.a, Color::GREEN.a);
this->sys.update();
- EXPECT_EQ(sprite.color.r, Color::GREEN.r);
- EXPECT_EQ(sprite.color.g, Color::GREEN.g);
- EXPECT_EQ(sprite.color.b, Color::GREEN.b);
- EXPECT_EQ(sprite.color.a, Color::GREEN.a);
+ EXPECT_EQ(sprite.data.color.r, Color::GREEN.r);
+ EXPECT_EQ(sprite.data.color.g, Color::GREEN.g);
+ EXPECT_EQ(sprite.data.color.b, Color::GREEN.b);
+ EXPECT_EQ(sprite.data.color.a, Color::GREEN.a);
}