diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-11 16:51:03 +0100 | 
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-11 16:51:03 +0100 | 
| commit | f0ecbea57a4d75905c4ee79608807187cd8f3e72 (patch) | |
| tree | 04a399dc7d400aaa9443be19ce13fd97e5822f95 | |
| parent | d228d4b3856606ad4395723b2703759a0ebe9832 (diff) | |
WIP
| -rw-r--r-- | src/crepe/Component.cpp | 5 | ||||
| -rw-r--r-- | src/crepe/Component.h | 8 | ||||
| -rw-r--r-- | src/crepe/api/LoopManager.cpp | 35 | ||||
| -rw-r--r-- | src/crepe/api/LoopManager.h | 21 | ||||
| -rw-r--r-- | src/crepe/api/LoopManager.hpp | 34 | ||||
| -rw-r--r-- | src/crepe/manager/ComponentManager.h | 24 | ||||
| -rw-r--r-- | src/crepe/manager/ReplayManager.h | 17 | ||||
| -rw-r--r-- | src/example/replay.cpp | 45 | 
8 files changed, 141 insertions, 48 deletions
| diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp index acfd35c..141e1a8 100644 --- a/src/crepe/Component.cpp +++ b/src/crepe/Component.cpp @@ -3,3 +3,8 @@  using namespace crepe;  Component::Component(game_object_id_t id) : game_object_id(id) {} + +Component & Component::operator=(const Component &) { +	return *this; +} + diff --git a/src/crepe/Component.h b/src/crepe/Component.h index eff5a58..47c5c34 100644 --- a/src/crepe/Component.h +++ b/src/crepe/Component.h @@ -32,9 +32,13 @@ protected:  	//! Only ComponentManager can create components  	friend class ComponentManager; -	Component(const Component &) = delete; +	// create snapshot +	Component(const Component &) = default; +	// restore snapshot +	virtual Component & operator=(const Component &); + +	// components are never moved  	Component(Component &&) = delete; -	virtual Component & operator=(const Component &) = delete;  	virtual Component & operator=(Component &&) = delete;  public: diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 637fbe1..ff428fd 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -13,18 +13,17 @@  using namespace crepe;  using namespace std; -LoopManager::LoopManager() -	: systems({ -		ScriptSystem{this->mediator}, -		PhysicsSystem{this->mediator}, -		CollisionSystem{this->mediator}, -		AnimatorSystem{this->mediator}, -		ParticleSystem{this->mediator}, -		RenderSystem{this->mediator}, -		InputSystem{this->mediator}, -		EventSystem{this->mediator}, -		AudioSystem{this->mediator}, -	}) { } +LoopManager::LoopManager() { +	this->load_system<ScriptSystem>(); +	this->load_system<PhysicsSystem>(); +	this->load_system<CollisionSystem>(); +	this->load_system<AnimatorSystem>(); +	this->load_system<ParticleSystem>(); +	this->load_system<RenderSystem>(); +	this->load_system<InputSystem>(); +	this->load_system<EventSystem>(); +	this->load_system<AudioSystem>(); +}  void LoopManager::start() {  	this->setup(); @@ -32,16 +31,16 @@ void LoopManager::start() {  }  void LoopManager::fixed_update() { -	for (System & system : this->systems) { -		if (!system.active) continue; -		system.fixed_update(); +	for (auto & [type, system] : this->systems) { +		if (!system->active) continue; +		system->fixed_update();  	}  }  void LoopManager::frame_update() { -	for (System & system : this->systems) { -		if (!system.active) continue; -		system.frame_update(); +	for (auto & [type, system] : this->systems) { +		if (!system->active) continue; +		system->frame_update();  	}  } diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 1183a4d..4b1fc1e 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -73,15 +73,32 @@ private:  	SaveManager save_manager{mediator};  	//! SDL context \todo no more singletons! -	SDLContext & sdl_context = SDLContext::get_instance(); +	SDLContext & sdl_context = mediator.sdl_context;  	//! Loop timer \todo no more singletons!  	LoopTimer & loop_timer = LoopTimer::get_instance();  private:  	/**  	 * \brief Collection of System instances +	 * +	 * This map holds System instances indexed by the system's class typeid. It is filled in the +	 * constructor of \c LoopManager using LoopManager::load_system. +	 */ +	std::unordered_map<std::type_index, std::unique_ptr<System>> systems; +	/** +	 * \brief Initialize a system +	 * \tparam T System type (must be derivative of \c System) +	 */ +	template <class T> +	void load_system(); +	/** +	 * \brief Retrieve a reference to ECS system +	 * \tparam T System type +	 * \returns Reference to system instance +	 * \throws std::runtime_error if the System is not initialized  	 */ -	std::vector<System> systems; +	template <class T> +	T & get_system();  };  } // namespace crepe diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp index 51afa70..627b281 100644 --- a/src/crepe/api/LoopManager.hpp +++ b/src/crepe/api/LoopManager.hpp @@ -1,5 +1,10 @@  #pragma once +#include <memory> +#include <cassert> +#include <format> + +#include "../system/System.h"  #include "LoopManager.h"  namespace crepe { @@ -9,4 +14,33 @@ void LoopManager::add_scene() {  	this->scene_manager.add_scene<T>();  } +template <class T> +T & LoopManager::get_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, "get_system must recieve a derivative class of System"); + +	const type_info & type = typeid(T); +	if (!this->systems.contains(type)) +		throw runtime_error(format("LoopManager: {} is not initialized", type.name())); + +	System * system = this->systems.at(type).get(); +	T * concrete_system = dynamic_cast<T *>(system); +	assert(concrete_system != nullptr); + +	return *concrete_system; +} + +template <class T> +void LoopManager::load_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, +			"load_system must recieve a derivative class of System"); + +	const type_info & type = typeid(T); +	if (this->systems.contains(type)) +		throw runtime_error(format("LoopManager: {} is already initialized", type.name())); +	System * system = new T(this->mediator); +	this->systems[type] = unique_ptr<System>(system); +} +  } // namespace crepe diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h index 19a8e81..94fd94f 100644 --- a/src/crepe/manager/ComponentManager.h +++ b/src/crepe/manager/ComponentManager.h @@ -21,13 +21,6 @@ class GameObject;   * This class manages all components. It provides methods to add, delete and get components.   */  class ComponentManager : public Manager { -	// TODO: This relation should be removed! I (loek) believe that the scene manager should -	// create/destroy components because the GameObject's are stored in concrete Scene classes, -	// which will in turn call GameObject's destructor, which will in turn call -	// ComponentManager::delete_components_by_id or something. This is a pretty major change, so -	// here is a comment and temporary fix instead :tada: -	friend class SceneManager; -  public:  	ComponentManager(Mediator & mediator);  	~ComponentManager(); // dbg_trace @@ -49,12 +42,7 @@ public:  						  const vec2 & position = {0, 0}, double rotation = 0,  						  double scale = 1); -protected: -	/** -	 * GameObject is used as an interface to add/remove components, and the game programmer is -	 * supposed to use it instead of interfacing with the component manager directly. -	 */ -	friend class GameObject; +public:  	/**  	 * \brief Add a component to the ComponentManager  	 * @@ -154,6 +142,16 @@ public:  	template <typename T>  	RefVector<T> get_components_by_tag(const std::string & tag) const; +	struct SnapshotComponent { +		by_type<by_id_index<std::vector<std::unique_ptr<Component>>>> components; +		Component component; +	}; +	struct Snapshot { +		 +	}; +	Snapshot save(); +	void restore(const Snapshot &); +  private:  	/**  	 * \brief Get object IDs by predicate function diff --git a/src/crepe/manager/ReplayManager.h b/src/crepe/manager/ReplayManager.h index 242eae4..c50196c 100644 --- a/src/crepe/manager/ReplayManager.h +++ b/src/crepe/manager/ReplayManager.h @@ -1,6 +1,8 @@  #pragma once  #include "Manager.h" +#include "ComponentManager.h" +#include <unordered_map>  namespace crepe { @@ -18,15 +20,18 @@ protected:  	void record_frame();  private: -	bool recording; -	struct Recording { -		recording_t id; -		std::vector<Memento> frames; -	}; +	typedef std::vector<ComponentManager::Snapshot> Recording; + +	bool recording = false; +	recording_t current_recording = -1; + + +	std::unordered_map<recording_t, std::unique_ptr<Recording>> memory;  public:  	void record_start();  	recording_t record_end(); -	 +	void play(recording_t handle); +	void release(recording_t handle);  };  } // namespace crepe diff --git a/src/example/replay.cpp b/src/example/replay.cpp index 6b1ed46..a3c7fba 100644 --- a/src/example/replay.cpp +++ b/src/example/replay.cpp @@ -1,4 +1,4 @@ -#include "util/OptionalRef.h" +#include <crepe/util/OptionalRef.h>  #include <crepe/api/BoxCollider.h>  #include <crepe/api/Camera.h>  #include <crepe/api/Color.h> @@ -13,6 +13,7 @@  #include <crepe/api/Transform.h>  #include <crepe/manager/ComponentManager.h>  #include <crepe/manager/Mediator.h> +#include <crepe/manager/ReplayManager.h>  using namespace crepe;  using namespace std; @@ -22,27 +23,55 @@ class AnimationScript : public Script {  	float t = 0;  	void init() { -		Log::logf("AnimationScript init");  		transform = &get_component<Transform>();  	}  	void update() { -		Log::logf("AnimationScript update"); -		t += 0.01; +		t += 0.05;  		transform->position = { sin(t), cos(t) };  	}  }; +class Timeline : public Script { +	unsigned i = 0; +	OptionalRef<ReplayManager> mgr; +	recording_t recording; +	void update() { +		ReplayManager & mgr = this->mgr; +		switch (i++) { +			default: break; +			case 10: +							 mgr.record_start(); +							 Log::logf("start"); +							 break; +			case 60: +							 this->recording = mgr.record_end(); +							 Log::logf("stop"); +							 break; +			case 70: +							 mgr.play(this->recording); +							 Log::logf("play"); +							 break; +			case 71: +							 mgr.release(this->recording); +							 Log::logf("end"); +							 break; +			case 72: +							 Log::logf("exit"); +							 throw; +							 break; +		}; +	} +}; +  class TestScene : public Scene {  public:  	using Scene::Scene;  	void load_scene() { -		Log::logf("Initializing scene...");  		Mediator & m = this->mediator;  		ComponentManager & mgr = m.component_manager; -  		GameObject cam = mgr.new_object("cam");  		cam.add_component<Camera>(ivec2{640,480},vec2{3,3}, Camera::Data{  			.bg_color = Color::WHITE, @@ -54,7 +83,9 @@ public:  			.size = { 0.5, 0.5 },  		});  		square.add_component<BehaviorScript>().set_script<AnimationScript>(); -		Log::logf("Done initializing scene"); + +		GameObject scapegoat = mgr.new_object(""); +		scapegoat.add_component<BehaviorScript>().set_script<Timeline>();  	}  	string get_name() const { return "scene1"; } |