aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/api
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-14 11:10:31 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-14 11:10:31 +0100
commit6e13510f3c6d4155707f748d237bb1fa05243450 (patch)
treeb21ca972d14aac56b7c58c85c54d8a2fd1278a7e /src/crepe/api
parent319d511135da1b58acb78ca939d7ee01fee4bbf3 (diff)
parentbe1e97bc7a494963ab1567492fafcda99e36f683 (diff)
merge `master` into `loek/audio`
Diffstat (limited to 'src/crepe/api')
-rw-r--r--src/crepe/api/Animator.cpp26
-rw-r--r--src/crepe/api/Animator.h76
-rw-r--r--src/crepe/api/AssetManager.h36
-rw-r--r--src/crepe/api/AudioSource.h2
-rw-r--r--src/crepe/api/CMakeLists.txt8
-rw-r--r--src/crepe/api/Camera.cpp18
-rw-r--r--src/crepe/api/Camera.h55
-rw-r--r--src/crepe/api/CircleCollider.h3
-rw-r--r--src/crepe/api/Color.cpp3
-rw-r--r--src/crepe/api/Color.h17
-rw-r--r--src/crepe/api/Config.cpp1
-rw-r--r--src/crepe/api/Config.h6
-rw-r--r--src/crepe/api/LoopManager.cpp55
-rw-r--r--src/crepe/api/LoopManager.h79
-rw-r--r--src/crepe/api/LoopTimer.cpp86
-rw-r--r--src/crepe/api/LoopTimer.h147
-rw-r--r--src/crepe/api/Metadata.cpp4
-rw-r--r--src/crepe/api/ParticleEmitter.cpp36
-rw-r--r--src/crepe/api/ParticleEmitter.h99
-rw-r--r--src/crepe/api/Rigidbody.cpp3
-rw-r--r--src/crepe/api/SaveManager.cpp53
-rw-r--r--src/crepe/api/SaveManager.h7
-rw-r--r--src/crepe/api/Sprite.cpp12
-rw-r--r--src/crepe/api/Sprite.h76
-rw-r--r--src/crepe/api/Texture.cpp15
-rw-r--r--src/crepe/api/Texture.h54
-rw-r--r--src/crepe/api/Transform.cpp5
-rw-r--r--src/crepe/api/Transform.h2
-rw-r--r--src/crepe/api/Vector2.cpp6
-rw-r--r--src/crepe/api/Vector2.h10
30 files changed, 870 insertions, 130 deletions
diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp
new file mode 100644
index 0000000..58fee2a
--- /dev/null
+++ b/src/crepe/api/Animator.cpp
@@ -0,0 +1,26 @@
+
+#include <cstdint>
+
+#include "util/log.h"
+
+#include "Animator.h"
+#include "Component.h"
+#include "Sprite.h"
+
+using namespace crepe;
+
+Animator::Animator(uint32_t id, Sprite & ss, int row, int col, int col_animator)
+ : Component(id),
+ spritesheet(ss),
+ row(row),
+ 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->active = false;
+}
+Animator::~Animator() { dbg_trace(); }
diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h
new file mode 100644
index 0000000..def0240
--- /dev/null
+++ b/src/crepe/api/Animator.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <cstdint>
+
+#include "Component.h"
+#include "Sprite.h"
+
+namespace crepe {
+class AnimatorSystem;
+class SDLContext;
+
+/**
+ * \brief The Animator component is used to animate sprites by managing the movement
+ * and frame changes within a sprite sheet.
+ *
+ * This component allows for controlling sprite animation through rows and columns of a sprite sheet.
+ * It can be used to play animations, loop them, or stop them.
+ */
+class Animator : public Component {
+
+public:
+ //TODO: need to implement this
+ void loop();
+ void stop();
+
+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.
+ *
+ * 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(); // 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.
+ Sprite & spritesheet;
+
+ //! The maximum number of columns in the sprite sheet.
+ const int col;
+
+ //! 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;
+
+ Rect animator_rect;
+
+ //TODO: Is this necessary?
+ //int fps;
+
+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/AssetManager.h b/src/crepe/api/AssetManager.h
index fefbed9..86a9902 100644
--- a/src/crepe/api/AssetManager.h
+++ b/src/crepe/api/AssetManager.h
@@ -7,9 +7,19 @@
namespace crepe {
+/**
+ * \brief The AssetManager is responsible for storing and managing assets over
+ * multiple scenes.
+ *
+ * The AssetManager ensures that assets are loaded once and can be accessed
+ * across different scenes. It caches assets to avoid reloading them every time
+ * a scene is loaded. Assets are retained in memory until the AssetManager is
+ * destroyed, at which point the cached assets are cleared.
+ */
class AssetManager {
private:
+ //! A cache that holds all the assets, accessible by their file path, over multiple scenes.
std::unordered_map<std::string, std::any> asset_cache;
private:
@@ -22,12 +32,32 @@ public:
AssetManager & operator=(const AssetManager &) = delete;
AssetManager & operator=(AssetManager &&) = delete;
+ /**
+ * \brief Retrieves the singleton instance of the AssetManager.
+ *
+ * \return A reference to the single instance of the AssetManager.
+ */
static AssetManager & get_instance();
public:
- template <typename asset>
- std::shared_ptr<asset> cache(const std::string & file_path,
- bool reload = false);
+ /**
+ * \brief Caches an asset by loading it from the given file path.
+ *
+ * \param file_path The path to the asset file to load.
+ * \param reload If true, the asset will be reloaded from the file, even if
+ * it is already cached.
+ * \tparam T The type of asset to cache (e.g., texture, sound, etc.).
+ *
+ * \return A shared pointer to the cached asset.
+ *
+ * This template function caches the asset at the given file path. If the
+ * asset is already cached and `reload` is false, the existing cached version
+ * will be returned. Otherwise, the asset will be reloaded and added to the
+ * cache.
+ */
+ template <typename T>
+ std::shared_ptr<T> cache(const std::string & file_path,
+ bool reload = false);
};
} // namespace crepe
diff --git a/src/crepe/api/AudioSource.h b/src/crepe/api/AudioSource.h
index fd2b6f1..5bc70f9 100644
--- a/src/crepe/api/AudioSource.h
+++ b/src/crepe/api/AudioSource.h
@@ -11,7 +11,7 @@ namespace crepe {
//! Audio source component
class AudioSource : public Component {
public:
- AudioSource(game_object_id_t id, std::unique_ptr<Asset> audio_clip);
+ AudioSource(game_object_id_t id, const Asset & source);
virtual ~AudioSource() = default;
public:
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 3b20142..85696c4 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -16,6 +16,10 @@ target_sources(crepe PUBLIC
Scene.cpp
SceneManager.cpp
Vector2.cpp
+ Camera.cpp
+ Animator.cpp
+ LoopManager.cpp
+ LoopTimer.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -38,4 +42,8 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
Metadata.h
SceneManager.h
SceneManager.hpp
+ Camera.h
+ Animator.h
+ LoopManager.h
+ LoopTimer.h
)
diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp
new file mode 100644
index 0000000..6355a03
--- /dev/null
+++ b/src/crepe/api/Camera.cpp
@@ -0,0 +1,18 @@
+
+#include <cstdint>
+
+#include "util/log.h"
+
+#include "Camera.h"
+#include "Color.h"
+#include "Component.h"
+
+using namespace crepe;
+
+Camera::Camera(uint32_t id, const Color & bg_color)
+ : Component(id),
+ bg_color(bg_color) {
+ dbg_trace();
+}
+
+Camera::~Camera() { dbg_trace(); }
diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h
new file mode 100644
index 0000000..ba3a9ef
--- /dev/null
+++ b/src/crepe/api/Camera.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <cstdint>
+
+#include "Color.h"
+#include "Component.h"
+
+namespace crepe {
+
+/**
+ * \class Camera
+ * \brief Represents a camera component for rendering in the game.
+ *
+ * The Camera class defines the view parameters, including background color,
+ * aspect ratio, position, and zoom level. It controls what part of the game
+ * world is visible on the screen.
+ */
+class Camera : public Component {
+
+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.
+ */
+ Camera(uint32_t id, const Color & bg_color);
+ ~Camera(); // dbg_trace only
+
+public:
+ //! Background color of the camera view.
+ Color bg_color;
+
+ //! Aspect ratio height for the camera.
+ double aspect_height = 480;
+
+ //! Aspect ratio width for the camera.
+ double aspect_width = 640;
+
+ //! X-coordinate of the camera position.
+ double x = 0.0;
+
+ //! Y-coordinate of the camera position.
+ double y = 0.0;
+
+ //! Zoom level of the camera view.
+ double zoom = 1.0;
+
+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; }
+};
+} // namespace crepe
diff --git a/src/crepe/api/CircleCollider.h b/src/crepe/api/CircleCollider.h
index caa7e43..e77a592 100644
--- a/src/crepe/api/CircleCollider.h
+++ b/src/crepe/api/CircleCollider.h
@@ -6,7 +6,8 @@ namespace crepe {
class CircleCollider : public Collider {
public:
CircleCollider(game_object_id_t game_object_id, int radius)
- : Collider(game_object_id), radius(radius) {}
+ : Collider(game_object_id),
+ radius(radius) {}
int radius;
};
diff --git a/src/crepe/api/Color.cpp b/src/crepe/api/Color.cpp
index fc6313d..9e5f187 100644
--- a/src/crepe/api/Color.cpp
+++ b/src/crepe/api/Color.cpp
@@ -11,8 +11,7 @@ Color Color::cyan = Color(0, 255, 255, 0);
Color Color::yellow = Color(255, 255, 0, 0);
Color Color::magenta = Color(255, 0, 255, 0);
-// FIXME: do we really need double precision for color values?
-Color::Color(double red, double green, double blue, double alpha) {
+Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
this->a = alpha;
this->r = red;
this->g = green;
diff --git a/src/crepe/api/Color.h b/src/crepe/api/Color.h
index 6b54888..aa47bf4 100644
--- a/src/crepe/api/Color.h
+++ b/src/crepe/api/Color.h
@@ -1,14 +1,17 @@
#pragma once
+#include <cstdint>
+
namespace crepe {
+// TODO: make Color a struct w/o constructors/destructors
class Color {
// FIXME: can't these colors be defined as a `static constexpr const Color`
// instead?
public:
- Color(double red, double green, double blue, double alpha);
+ Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
static const Color & get_white();
static const Color & get_red();
static const Color & get_green();
@@ -19,10 +22,11 @@ public:
static const Color & get_black();
private:
- double r;
- double g;
- double b;
- double a;
+ // TODO: why are these private!?
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
static Color white;
static Color red;
@@ -32,6 +36,9 @@ private:
static Color magenta;
static Color yellow;
static Color black;
+
+private:
+ friend class SDLContext;
};
} // namespace crepe
diff --git a/src/crepe/api/Config.cpp b/src/crepe/api/Config.cpp
index d6206da..0100bcc 100644
--- a/src/crepe/api/Config.cpp
+++ b/src/crepe/api/Config.cpp
@@ -6,4 +6,3 @@ Config & Config::get_instance() {
static Config instance;
return instance;
}
-
diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h
index 56e3af5..8c9e643 100644
--- a/src/crepe/api/Config.h
+++ b/src/crepe/api/Config.h
@@ -7,6 +7,7 @@ namespace crepe {
class Config {
private:
Config() = default;
+
public:
~Config() = default;
@@ -16,8 +17,8 @@ public:
// singleton
Config(const Config &) = delete;
Config(Config &&) = delete;
- Config & operator = (const Config &) = delete;
- Config & operator = (Config &&) = delete;
+ Config & operator=(const Config &) = delete;
+ Config & operator=(Config &&) = delete;
public:
//! Logging-related settings
@@ -60,4 +61,3 @@ public:
};
} // namespace crepe
-
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
new file mode 100644
index 0000000..2e9823f
--- /dev/null
+++ b/src/crepe/api/LoopManager.cpp
@@ -0,0 +1,55 @@
+
+#include "../facade/SDLContext.h"
+#include "../system/RenderSystem.h"
+#include "../system/ScriptSystem.h"
+
+#include "LoopManager.h"
+#include "LoopTimer.h"
+
+using namespace crepe;
+
+LoopManager::LoopManager() {}
+void LoopManager::process_input() {
+ SDLContext::get_instance().handle_events(this->game_running);
+}
+void LoopManager::start() {
+ this->setup();
+ this->loop();
+}
+void LoopManager::set_running(bool running) { this->game_running = running; }
+
+void LoopManager::fixed_update() {}
+
+void LoopManager::loop() {
+ LoopTimer & timer = LoopTimer::get_instance();
+ timer.start();
+
+ while (game_running) {
+ timer.update();
+
+ while (timer.get_lag() >= timer.get_fixed_delta_time()) {
+ this->process_input();
+ this->fixed_update();
+ timer.advance_fixed_update();
+ }
+
+ this->update();
+ this->render();
+
+ timer.enforce_frame_rate();
+ }
+}
+
+void LoopManager::setup() {
+ this->game_running = true;
+ LoopTimer::get_instance().start();
+ LoopTimer::get_instance().set_fps(60);
+}
+
+void LoopManager::render() {
+ if (this->game_running) {
+ RenderSystem::get_instance().update();
+ }
+}
+
+void LoopManager::update() { LoopTimer & timer = LoopTimer::get_instance(); }
diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h
new file mode 100644
index 0000000..2f03193
--- /dev/null
+++ b/src/crepe/api/LoopManager.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <memory>
+
+class RenderSystem;
+class SDLContext;
+class LoopTimer;
+class ScriptSystem;
+class SoundSystem;
+class ParticleSystem;
+class PhysicsSystem;
+class AnimatorSystem;
+class CollisionSystem;
+namespace crepe {
+
+class LoopManager {
+public:
+ void start();
+ LoopManager();
+
+private:
+ /**
+ * \brief Setup function for one-time initialization.
+ *
+ * This function initializes necessary components for the game.
+ */
+ void setup();
+ /**
+ * \brief Main game loop function.
+ *
+ * This function runs the main loop, handling game updates and rendering.
+ */
+ void loop();
+
+ /**
+ * \brief Function for handling input-related system calls.
+ *
+ * Processes user inputs from keyboard and mouse.
+ */
+ void process_input();
+
+ /**
+ * \brief Per-frame update.
+ *
+ * Updates the game state based on the elapsed time since the last frame.
+ */
+ void update();
+
+ /**
+ * \brief Late update which is called after update().
+ *
+ * This function can be used for final adjustments before rendering.
+ */
+ void late_update();
+
+ /**
+ * \brief Fixed update executed at a fixed rate.
+ *
+ * This function updates physics and game logic based on LoopTimer's fixed_delta_time.
+ */
+ void fixed_update();
+ /**
+ * \brief Set game running variable
+ *
+ * \param running running (false = game shutdown, true = game running)
+ */
+ void set_running(bool running);
+ /**
+ * \brief Function for executing render-related systems.
+ *
+ * Renders the current state of the game to the screen.
+ */
+ void render();
+
+ bool game_running = false;
+ //#TODO add system instances
+};
+
+} // namespace crepe
diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp
new file mode 100644
index 0000000..8f09e41
--- /dev/null
+++ b/src/crepe/api/LoopTimer.cpp
@@ -0,0 +1,86 @@
+#include <chrono>
+
+#include "../facade/SDLContext.h"
+#include "../util/log.h"
+
+#include "LoopTimer.h"
+
+using namespace crepe;
+
+LoopTimer::LoopTimer() { dbg_trace(); }
+
+LoopTimer & LoopTimer::get_instance() {
+ static LoopTimer instance;
+ return instance;
+}
+
+void LoopTimer::start() {
+ this->last_frame_time = std::chrono::steady_clock::now();
+ this->elapsed_time = std::chrono::milliseconds(0);
+ this->elapsed_fixed_time = std::chrono::milliseconds(0);
+ this->delta_time = std::chrono::milliseconds(0);
+}
+
+void LoopTimer::update() {
+ auto current_frame_time = std::chrono::steady_clock::now();
+ // Convert to duration in seconds for delta time
+ this->delta_time
+ = std::chrono::duration_cast<std::chrono::duration<double>>(
+ current_frame_time - last_frame_time);
+
+ if (this->delta_time > this->maximum_delta_time) {
+ this->delta_time = this->maximum_delta_time;
+ }
+
+ this->delta_time *= this->game_scale;
+ this->elapsed_time += this->delta_time;
+ this->last_frame_time = current_frame_time;
+}
+
+double LoopTimer::get_delta_time() const { return this->delta_time.count(); }
+
+double LoopTimer::get_current_time() const {
+ return this->elapsed_time.count();
+}
+
+void LoopTimer::advance_fixed_update() {
+ this->elapsed_fixed_time += this->fixed_delta_time;
+}
+
+double LoopTimer::get_fixed_delta_time() const {
+ return this->fixed_delta_time.count();
+}
+
+void LoopTimer::set_fps(int fps) {
+ this->fps = fps;
+ // target time per frame in seconds
+ this->frame_target_time = std::chrono::seconds(1) / fps;
+}
+
+int LoopTimer::get_fps() const { return this->fps; }
+
+void LoopTimer::set_game_scale(double value) { this->game_scale = value; }
+
+double LoopTimer::get_game_scale() const { return this->game_scale; }
+void LoopTimer::enforce_frame_rate() {
+ std::chrono::steady_clock::time_point current_frame_time
+ = std::chrono::steady_clock::now();
+ std::chrono::milliseconds frame_duration
+ = std::chrono::duration_cast<std::chrono::milliseconds>(
+ current_frame_time - this->last_frame_time);
+
+ if (frame_duration < this->frame_target_time) {
+ std::chrono::milliseconds delay_time
+ = std::chrono::duration_cast<std::chrono::milliseconds>(
+ this->frame_target_time - frame_duration);
+ if (delay_time.count() > 0) {
+ SDLContext::get_instance().delay(delay_time.count());
+ }
+ }
+
+ this->last_frame_time = current_frame_time;
+}
+
+double LoopTimer::get_lag() const {
+ return (this->elapsed_time - this->elapsed_fixed_time).count();
+}
diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h
new file mode 100644
index 0000000..85687be
--- /dev/null
+++ b/src/crepe/api/LoopTimer.h
@@ -0,0 +1,147 @@
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+
+namespace crepe {
+
+class LoopTimer {
+public:
+ /**
+ * \brief Get the singleton instance of LoopTimer.
+ *
+ * \return A reference to the LoopTimer instance.
+ */
+ static LoopTimer & get_instance();
+
+ /**
+ * \brief Get the current delta time for the current frame.
+ *
+ * \return Delta time in seconds since the last frame.
+ */
+ double get_delta_time() const;
+
+ /**
+ * \brief Get the current game time.
+ *
+ * \note The current game time may vary from real-world elapsed time.
+ * It is the cumulative sum of each frame's delta time.
+ *
+ * \return Elapsed game time in seconds.
+ */
+ double get_current_time() const;
+
+ /**
+ * \brief Set the target frames per second (FPS).
+ *
+ * \param fps The desired frames rendered per second.
+ */
+ void set_fps(int fps);
+
+ /**
+ * \brief Get the current frames per second (FPS).
+ *
+ * \return Current FPS.
+ */
+ int get_fps() const;
+
+ /**
+ * \brief Get the current game scale.
+ *
+ * \return The current game scale, where 0 = paused, 1 = normal speed, and values > 1 speed up the game.
+ */
+ double get_game_scale() const;
+
+ /**
+ * \brief Set the game scale.
+ *
+ * \param game_scale The desired game scale (0 = pause, 1 = normal speed, > 1 = speed up).
+ */
+ void set_game_scale(double game_scale);
+
+private:
+ friend class LoopManager;
+
+ /**
+ * \brief Start the loop timer.
+ *
+ * Initializes the timer to begin tracking frame times.
+ */
+ void start();
+
+ /**
+ * \brief Enforce the frame rate limit.
+ *
+ * Ensures that the game loop does not exceed the target FPS by delaying
+ * frame updates as necessary.
+ */
+ void enforce_frame_rate();
+
+ /**
+ * \brief Get the fixed delta time for consistent updates.
+ *
+ * Fixed delta time is used for operations that require uniform time steps,
+ * such as physics calculations.
+ *
+ * \return Fixed delta time in seconds.
+ */
+ double get_fixed_delta_time() const;
+
+ /**
+ * \brief Get the accumulated lag in the game loop.
+ *
+ * Lag represents the difference between the target frame time and the
+ * actual frame time, useful for managing fixed update intervals.
+ *
+ * \return Accumulated lag in seconds.
+ */
+ double get_lag() const;
+
+ /**
+ * \brief Construct a new LoopTimer object.
+ *
+ * Private constructor for singleton pattern to restrict instantiation
+ * outside the class.
+ */
+ LoopTimer();
+
+ /**
+ * \brief Update the timer to the current frame.
+ *
+ * Calculates and updates the delta time for the current frame and adds it to
+ * the cumulative game time.
+ */
+ void update();
+
+ /**
+ * \brief Advance the game loop by a fixed update interval.
+ *
+ * This method progresses the game state by a consistent, fixed time step,
+ * allowing for stable updates independent of frame rate fluctuations.
+ */
+ void advance_fixed_update();
+
+private:
+ //! Current frames per second
+ int fps = 50;
+ //! Current game scale
+ double game_scale = 1;
+ //! Maximum delta time in seconds to avoid large jumps
+ std::chrono::duration<double> maximum_delta_time{0.25};
+ //! Delta time for the current frame in seconds
+ std::chrono::duration<double> delta_time{0.0};
+ //! Target time per frame in seconds
+ std::chrono::duration<double> frame_target_time
+ = std::chrono::seconds(1) / fps;
+ //! Fixed delta time for fixed updates in seconds
+ std::chrono::duration<double> fixed_delta_time
+ = std::chrono::seconds(1) / 50;
+ //! Total elapsed game time in seconds
+ std::chrono::duration<double> elapsed_time{0.0};
+ //! Total elapsed time for fixed updates in seconds
+ std::chrono::duration<double> elapsed_fixed_time{0.0};
+ //! Time of the last frame
+ std::chrono::steady_clock::time_point last_frame_time;
+};
+
+} // namespace crepe
diff --git a/src/crepe/api/Metadata.cpp b/src/crepe/api/Metadata.cpp
index 76f11d7..d421de5 100644
--- a/src/crepe/api/Metadata.cpp
+++ b/src/crepe/api/Metadata.cpp
@@ -4,4 +4,6 @@ using namespace crepe;
using namespace std;
Metadata::Metadata(game_object_id_t id, const string & name, const string & tag)
- : Component(id), name(name), tag(tag) {}
+ : Component(id),
+ name(name),
+ tag(tag) {}
diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp
index 3b2e2f2..35f960d 100644
--- a/src/crepe/api/ParticleEmitter.cpp
+++ b/src/crepe/api/ParticleEmitter.cpp
@@ -1,36 +1,12 @@
-#include <ctime>
-#include <iostream>
-
-#include "Particle.h"
#include "ParticleEmitter.h"
using namespace crepe;
-ParticleEmitter::ParticleEmitter(game_object_id_t id, uint32_t max_particles,
- uint32_t emission_rate, uint32_t speed,
- uint32_t speed_offset, uint32_t angle,
- uint32_t angleOffset, float begin_lifespan,
- float end_lifespan)
- : Component(id), max_particles(max_particles), emission_rate(emission_rate),
- speed(speed), speed_offset(speed_offset), position{0, 0},
- begin_lifespan(begin_lifespan), end_lifespan(end_lifespan) {
- std::srand(
- static_cast<uint32_t>(std::time(nullptr))); // initialize random seed
- std::cout << "Create emitter" << std::endl;
- // FIXME: Why do these expressions start with `360 +`, only to be `% 360`'d
- // right after? This does not make any sense to me.
- min_angle = (360 + angle - (angleOffset % 360)) % 360;
- max_angle = (360 + angle + (angleOffset % 360)) % 360;
- position.x = 400; // FIXME: what are these magic values?
- position.y = 400;
- for (size_t i = 0; i < max_particles; i++) {
- this->particles.emplace_back();
- }
-}
-
-ParticleEmitter::~ParticleEmitter() {
- std::vector<Particle>::iterator it = this->particles.begin();
- while (it != this->particles.end()) {
- it = this->particles.erase(it);
+ParticleEmitter::ParticleEmitter(game_object_id_t game_object_id,
+ const Data & data)
+ : Component(game_object_id),
+ data(data) {
+ for (size_t i = 0; i < this->data.max_particles; i++) {
+ this->data.particles.emplace_back();
}
}
diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h
index 5939723..a9e872f 100644
--- a/src/crepe/api/ParticleEmitter.h
+++ b/src/crepe/api/ParticleEmitter.h
@@ -1,42 +1,85 @@
#pragma once
-#include <cstdint>
#include <vector>
#include "Component.h"
#include "Particle.h"
+#include "Vector2.h"
namespace crepe {
+class Sprite;
+
+/**
+ * \brief Data holder for particle emission parameters.
+ *
+ * The ParticleEmitter class stores configuration data for particle properties,
+ * defining the characteristics and boundaries of particle emissions.
+ */
class ParticleEmitter : public Component {
public:
- ParticleEmitter(game_object_id_t id, uint32_t max_particles,
- uint32_t emission_rate, uint32_t speed,
- uint32_t speed_offset, uint32_t angle, uint32_t angleOffset,
- float begin_lifespan, float end_lifespan);
- ~ParticleEmitter();
-
- //! position of the emitter
- Position position;
- //! maximum number of particles
- uint32_t max_particles;
- //! rate of particle emission
- uint32_t emission_rate;
- //! base speed of the particles
- uint32_t speed;
- //! offset for random speed variation
- uint32_t speed_offset;
- //! min angle of particle emission
- uint32_t min_angle;
- //! max angle of particle emission
- uint32_t max_angle;
- //! begin Lifespan of particle (only visual)
- float begin_lifespan;
- //! begin Lifespan of particle
- float end_lifespan;
-
- //! collection of particles
- std::vector<Particle> particles;
+ /**
+ * \brief Defines the boundary within which particles are constrained.
+ *
+ * This structure specifies the boundary's size and offset, as well as the
+ * behavior of particles upon reaching the boundary limits.
+ */
+ struct Boundary {
+ //! boundary width (midpoint is emitter location)
+ double width = 0.0;
+ //! boundary height (midpoint is emitter location)
+ double height = 0.0;
+ //! boundary offset from particle emitter location
+ Vector2 offset;
+ //! reset on exit or stop velocity and set max postion
+ bool reset_on_exit = false;
+ };
+
+ /**
+ * \brief Holds parameters that control particle emission.
+ *
+ * Contains settings for the emitter’s position, particle speed, angle, lifespan,
+ * boundary, and the sprite used for rendering particles.
+ */
+ struct Data {
+ //! position of the emitter
+ Vector2 position;
+ //! maximum number of particles
+ const unsigned int max_particles = 0;
+ //! rate of particle emission per update (Lowest value = 0.001 any lower is ignored)
+ double emission_rate = 0;
+ //! min speed of the particles
+ double min_speed = 0;
+ //! min speed of the particles
+ double max_speed = 0;
+ //! min angle of particle emission
+ double min_angle = 0;
+ //! max angle of particle emission
+ double max_angle = 0;
+ //! begin Lifespan of particle (only visual)
+ double begin_lifespan = 0.0;
+ //! end Lifespan of particle
+ double end_lifespan = 0.0;
+ //! force over time (physics)
+ Vector2 force_over_time;
+ //! particle boundary
+ Boundary boundary;
+ //! collection of particles
+ std::vector<Particle> particles;
+ //! sprite reference
+ const Sprite & sprite;
+ };
+
+public:
+ /**
+ * \param game_object_id Identifier for the game object using this emitter.
+ * \param data Configuration data defining particle properties.
+ */
+ ParticleEmitter(game_object_id_t game_object_id, const Data & data);
+
+public:
+ //! Configuration data for particle emission settings.
+ Data data;
};
} // namespace crepe
diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp
index cbf1325..3bf1c5b 100644
--- a/src/crepe/api/Rigidbody.cpp
+++ b/src/crepe/api/Rigidbody.cpp
@@ -3,7 +3,8 @@
using namespace crepe;
crepe::Rigidbody::Rigidbody(uint32_t game_object_id, const Data & data)
- : Component(game_object_id), data(data) {}
+ : Component(game_object_id),
+ data(data) {}
void crepe::Rigidbody::add_force_linear(const Vector2 & force) {
this->data.linear_velocity += force;
diff --git a/src/crepe/api/SaveManager.cpp b/src/crepe/api/SaveManager.cpp
index 23587e4..43276c5 100644
--- a/src/crepe/api/SaveManager.cpp
+++ b/src/crepe/api/SaveManager.cpp
@@ -2,8 +2,8 @@
#include "../util/log.h"
#include "Config.h"
-#include "ValueBroker.h"
#include "SaveManager.h"
+#include "ValueBroker.h"
using namespace std;
using namespace crepe;
@@ -65,17 +65,33 @@ string SaveManager::deserialize(const string & value) const noexcept {
return value;
}
-template <> uint8_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<uint64_t>(value); }
-template <> int8_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<int64_t>(value); }
-template <> uint16_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<uint64_t>(value); }
-template <> int16_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<int64_t>(value); }
-template <> uint32_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<uint64_t>(value); }
-template <> int32_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<int64_t>(value); }
-
-SaveManager::SaveManager() {
- dbg_trace();
+template <>
+uint8_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<uint64_t>(value);
+}
+template <>
+int8_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<int64_t>(value);
+}
+template <>
+uint16_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<uint64_t>(value);
+}
+template <>
+int16_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<int64_t>(value);
+}
+template <>
+uint32_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<uint64_t>(value);
+}
+template <>
+int32_t SaveManager::deserialize(const string & value) const noexcept {
+ return deserialize<int64_t>(value);
}
+SaveManager::SaveManager() { dbg_trace(); }
+
SaveManager & SaveManager::get_instance() {
dbg_trace();
static SaveManager instance;
@@ -118,17 +134,19 @@ template void SaveManager::set(const string &, const double &);
template <typename T>
ValueBroker<T> SaveManager::get(const string & key, const T & default_value) {
- if (!this->has(key))
- this->set<T>(key, default_value);
+ if (!this->has(key)) this->set<T>(key, default_value);
return this->get<T>(key);
}
template ValueBroker<uint8_t> SaveManager::get(const string &, const uint8_t &);
template ValueBroker<int8_t> SaveManager::get(const string &, const int8_t &);
-template ValueBroker<uint16_t> SaveManager::get(const string &, const uint16_t &);
+template ValueBroker<uint16_t> SaveManager::get(const string &,
+ const uint16_t &);
template ValueBroker<int16_t> SaveManager::get(const string &, const int16_t &);
-template ValueBroker<uint32_t> SaveManager::get(const string &, const uint32_t &);
+template ValueBroker<uint32_t> SaveManager::get(const string &,
+ const uint32_t &);
template ValueBroker<int32_t> SaveManager::get(const string &, const int32_t &);
-template ValueBroker<uint64_t> SaveManager::get(const string &, const uint64_t &);
+template ValueBroker<uint64_t> SaveManager::get(const string &,
+ const uint64_t &);
template ValueBroker<int64_t> SaveManager::get(const string &, const int64_t &);
template ValueBroker<float> SaveManager::get(const string &, const float &);
template ValueBroker<double> SaveManager::get(const string &, const double &);
@@ -138,8 +156,8 @@ template <typename T>
ValueBroker<T> SaveManager::get(const string & key) {
T value;
return {
- [this, key] (const T & target) { this->set<T>(key, target); },
- [this, key, value] () mutable -> const T & {
+ [this, key](const T & target) { this->set<T>(key, target); },
+ [this, key, value]() mutable -> const T & {
value = this->deserialize<T>(this->get_db().get(key));
return value;
},
@@ -156,4 +174,3 @@ template ValueBroker<int64_t> SaveManager::get(const string &);
template ValueBroker<float> SaveManager::get(const string &);
template ValueBroker<double> SaveManager::get(const string &);
template ValueBroker<string> SaveManager::get(const string &);
-
diff --git a/src/crepe/api/SaveManager.h b/src/crepe/api/SaveManager.h
index 3073656..4be85fb 100644
--- a/src/crepe/api/SaveManager.h
+++ b/src/crepe/api/SaveManager.h
@@ -93,8 +93,8 @@ public:
static SaveManager & get_instance();
SaveManager(const SaveManager &) = delete;
SaveManager(SaveManager &&) = delete;
- SaveManager & operator = (const SaveManager &) = delete;
- SaveManager & operator = (SaveManager &&) = delete;
+ SaveManager & operator=(const SaveManager &) = delete;
+ SaveManager & operator=(SaveManager &&) = delete;
private:
/**
@@ -110,5 +110,4 @@ private:
static DB & get_db();
};
-}
-
+} // namespace crepe
diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp
index d3465c7..6f0433f 100644
--- a/src/crepe/api/Sprite.cpp
+++ b/src/crepe/api/Sprite.cpp
@@ -1,7 +1,7 @@
-#include <cstdint>
#include <memory>
#include "../util/log.h"
+#include "facade/SDLContext.h"
#include "Component.h"
#include "Sprite.h"
@@ -10,10 +10,16 @@
using namespace std;
using namespace crepe;
-Sprite::Sprite(game_object_id_t id, shared_ptr<Texture> image,
+Sprite::Sprite(game_object_id_t id, const shared_ptr<Texture> image,
const Color & color, const FlipSettings & flip)
- : Component(id), color(color), flip(flip), sprite_image(image) {
+ : Component(id),
+ color(color),
+ flip(flip),
+ sprite_image(image) {
dbg_trace();
+
+ this->sprite_rect.w = sprite_image->get_width();
+ this->sprite_rect.h = sprite_image->get_height();
}
Sprite::~Sprite() { dbg_trace(); }
diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h
index 00dcb27..deb3f93 100644
--- a/src/crepe/api/Sprite.h
+++ b/src/crepe/api/Sprite.h
@@ -1,32 +1,88 @@
#pragma once
-#include <SDL2/SDL_rect.h>
#include <cstdint>
#include <memory>
-#include "api/Color.h"
-#include "api/Texture.h"
-
+#include "Color.h"
#include "Component.h"
+#include "Texture.h"
namespace crepe {
+struct Rect {
+ int w = 0;
+ int h = 0;
+ int x = 0;
+ int y = 0;
+};
+
struct FlipSettings {
- bool flip_x = true;
- bool flip_y = true;
+ bool flip_x = false;
+ bool flip_y = false;
};
+class SDLContext;
+class Animator;
+class AnimatorSystem;
+
+/**
+ * \brief Represents a renderable sprite component.
+ *
+ * A renderable sprite that can be displayed in the game. It includes a texture,
+ * color, and flip settings, and is managed in layers with defined sorting orders.
+ */
class Sprite : public Component {
public:
- Sprite(game_object_id_t id, std::shared_ptr<Texture> image,
+ // 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.
+ */
+ Sprite(game_object_id_t id, const std::shared_ptr<Texture> image,
const Color & color, const FlipSettings & flip);
+
+ /**
+ * \brief Destroys the Sprite instance.
+ */
~Sprite();
- std::shared_ptr<Texture> sprite_image;
+
+ //! Texture used for the sprite
+ const std::shared_ptr<Texture> sprite_image;
+ //! Color tint of the sprite
Color color;
+ //! Flip settings for the sprite
FlipSettings flip;
- uint8_t sorting_in_layer;
- uint8_t order_in_layer;
+ //! Layer sorting level of the sprite
+ uint8_t sorting_in_layer = 0;
+ //! Order within the sorting layer
+ uint8_t order_in_layer = 0;
+
+public:
+ /**
+ * \brief Gets the maximum number of instances allowed for this sprite.
+ * \return Maximum instance count as an integer.
+ *
+ * For now is this number randomly picked. I think it will eventually be 1.
+ */
+ virtual int get_instances_max() const { return 10; }
+
+private:
+ //! Reads the sprite_rect of sprite
+ friend class SDLContext;
+
+ //! Reads the all the variables plus the sprite_rect
+ friend class Animator;
+
+ //! Reads the all the variables plus the sprite_rect
+ friend class AnimatorSystem;
+
+ //! Render area of the sprite this will also be adjusted by the AnimatorSystem if an Animator object is present in GameObject
+ Rect sprite_rect;
};
} // namespace crepe
diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp
index 8fc5c13..5ebd23d 100644
--- a/src/crepe/api/Texture.cpp
+++ b/src/crepe/api/Texture.cpp
@@ -21,12 +21,19 @@ Texture::Texture(const char * src) {
Texture::~Texture() {
dbg_trace();
- if (this->texture != nullptr) {
- SDL_DestroyTexture(this->texture);
- }
+ this->texture.reset();
}
void Texture::load(unique_ptr<Asset> res) {
SDLContext & ctx = SDLContext::get_instance();
- this->texture = ctx.texture_from_path(res->canonical());
+ this->texture = std::move(ctx.texture_from_path(res->canonical()));
+}
+
+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_width(*this);
}
diff --git a/src/crepe/api/Texture.h b/src/crepe/api/Texture.h
index 9a86f6f..b89bc17 100644
--- a/src/crepe/api/Texture.h
+++ b/src/crepe/api/Texture.h
@@ -3,31 +3,75 @@
// FIXME: this header can't be included because this is an API header, and SDL2
// development headers won't be bundled with crepe. Why is this facade in the
// API namespace?
+
#include <SDL2/SDL_render.h>
+#include <functional>
#include <memory>
#include "Asset.h"
namespace crepe {
-class SDLContext;
-}
-namespace crepe {
+class SDLContext;
+class Animator;
+/**
+ * \class Texture
+ * \brief Manages texture loading and properties.
+ *
+ * The Texture class is responsible for loading an image from a source
+ * and providing access to its dimensions. Textures can be used for rendering.
+ */
class Texture {
public:
+ /**
+ * \brief Constructs a Texture from a file path.
+ * \param src Path to the image file to be loaded as a texture.
+ */
Texture(const char * src);
+
+ /**
+ * \brief Constructs a Texture from an Asset resource.
+ * \param res Unique pointer to an Asset resource containing texture data.
+ */
Texture(std::unique_ptr<Asset> res);
+
+ /**
+ * \brief Destroys the Texture instance, freeing associated resources.
+ */
~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;
+
+ /**
+ * \brief Gets the height of the texture.
+ * \return Height of the texture in pixels.
+ */
+ int get_height() const;
private:
+ /**
+ * \brief Loads the texture from an Asset resource.
+ * \param res Unique pointer to an Asset resource to load the texture from.
+ */
void load(std::unique_ptr<Asset> res);
private:
- SDL_Texture * texture = nullptr;
+ //! The texture of the class from the library
+ std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> texture;
+
+ //! Grants SDLContext access to private members.
+ friend class SDLContext;
- friend class crepe::SDLContext;
+ //! Grants Animator access to private members.
+ friend class Animator;
};
} // namespace crepe
diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp
index a244bc5..e401120 100644
--- a/src/crepe/api/Transform.cpp
+++ b/src/crepe/api/Transform.cpp
@@ -6,6 +6,9 @@ using namespace crepe;
Transform::Transform(game_object_id_t id, const Vector2 & point,
double rotation, double scale)
- : Component(id), position(point), rotation(rotation), scale(scale) {
+ : Component(id),
+ position(point),
+ rotation(rotation),
+ scale(scale) {
dbg_trace();
}
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index d7a5b8a..756e45b 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -32,7 +32,7 @@ public:
public:
//! Translation (shift)
Vector2 position;
- //! Rotation, in radians
+ //! Rotation, in degrees
double rotation;
//! Multiplication factor
double scale;
diff --git a/src/crepe/api/Vector2.cpp b/src/crepe/api/Vector2.cpp
index 09bb59b..09b3fa3 100644
--- a/src/crepe/api/Vector2.cpp
+++ b/src/crepe/api/Vector2.cpp
@@ -3,7 +3,7 @@
namespace crepe {
// Constructor with initial values
-Vector2::Vector2(float x, float y) : x(x), y(y) {}
+Vector2::Vector2(double x, double y) : x(x), y(y) {}
// Subtracts another vector from this vector and returns the result.
Vector2 Vector2::operator-(const Vector2 & other) const {
@@ -16,7 +16,7 @@ Vector2 Vector2::operator+(const Vector2 & other) const {
}
// Multiplies this vector by a scalar and returns the result.
-Vector2 Vector2::operator*(float scalar) const {
+Vector2 Vector2::operator*(double scalar) const {
return {x * scalar, y * scalar};
}
@@ -35,7 +35,7 @@ Vector2 & Vector2::operator+=(const Vector2 & other) {
}
// Adds a scalar value to both components of this vector and updates this vector.
-Vector2 & Vector2::operator+=(float other) {
+Vector2 & Vector2::operator+=(double other) {
x += other;
y += other;
return *this;
diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h
index 741951b..5a57484 100644
--- a/src/crepe/api/Vector2.h
+++ b/src/crepe/api/Vector2.h
@@ -6,15 +6,15 @@ namespace crepe {
class Vector2 {
public:
//! X component of the vector
- float x;
+ double x;
//! Y component of the vector
- float y;
+ double y;
//! Default constructor
Vector2() = default;
//! Constructor with initial values
- Vector2(float x, float y);
+ Vector2(double x, double y);
//! Subtracts another vector from this vector and returns the result.
Vector2 operator-(const Vector2 & other) const;
@@ -23,7 +23,7 @@ public:
Vector2 operator+(const Vector2 & other) const;
//! Multiplies this vector by a scalar and returns the result.
- Vector2 operator*(float scalar) const;
+ Vector2 operator*(double scalar) const;
//! Multiplies this vector by another vector element-wise and updates this vector.
Vector2 & operator*=(const Vector2 & other);
@@ -32,7 +32,7 @@ public:
Vector2 & operator+=(const Vector2 & other);
//! Adds a scalar value to both components of this vector and updates this vector.
- Vector2 & operator+=(float other);
+ Vector2 & operator+=(double other);
//! Returns the negation of this vector.
Vector2 operator-() const;