ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
scene.h
Go to the documentation of this file.
1
8
9#ifndef ASW_SCENE_H
10#define ASW_SCENE_H
11
12#include <chrono>
13#include <iostream>
14#include <memory>
15#include <unordered_map>
16#include <vector>
17
18#include "./core.h"
19#include "./display.h"
20#include "./game.h"
21
22#ifdef __EMSCRIPTEN__
23#include <emscripten.h>
24#endif
25
26namespace asw::scene {
27 using namespace std::chrono_literals;
28
30 constexpr auto timestep = 8ms;
31
33 template <typename T>
34 class SceneManager;
35
41 template <typename T>
42 class Scene {
43 public:
50
52 virtual ~Scene() = default;
53
59 virtual void init() {};
60
66 virtual void update(float deltaTime) {
67 // Erase inactive objects
68 objects.erase(
69 std::remove_if(objects.begin(), objects.end(),
70 [](const std::shared_ptr<game::GameObject>& obj) {
71 return !obj->alive;
72 }),
73 objects.end());
74
75 // Update all objects in the scene
76 for (auto& obj : objects) {
77 if (obj->active && obj->alive) {
78 obj->update(deltaTime);
79 }
80 }
81
82 // Create new objects
83 for (auto& obj : objectsToCreate) {
84 objects.push_back(obj);
85 }
86
87 // Clear the objects to create
88 objectsToCreate.clear();
89 };
90
95 virtual void draw() {
96 // Sort objects by z-index
97 std::sort(objects.begin(), objects.end(),
98 [](const std::shared_ptr<game::GameObject>& a,
99 const std::shared_ptr<game::GameObject>& b) {
100 return a->zIndex < b->zIndex;
101 });
102
103 for (auto& obj : objects) {
104 if (obj->active) {
105 obj->draw();
106 }
107 }
108 };
109
115 virtual void cleanup() { objects.clear(); };
116
121 void registerObject(const std::shared_ptr<game::GameObject> obj) {
122 objects.push_back(obj);
123 }
124
129 template <typename ObjectType, typename... Args>
130 std::shared_ptr<ObjectType> createObject(Args&&... args) {
131 static_assert(std::is_base_of_v<game::GameObject, ObjectType>,
132 "ObjectType must be derived from Scene<T>");
133 static_assert(
134 std::is_constructible_v<ObjectType, Args...>,
135 "ObjectType must be constructible with the given arguments");
136
137 auto obj = std::make_shared<ObjectType>(std::forward<Args>(args)...);
138 objectsToCreate.emplace_back(obj);
139 return obj;
140 }
141
146 std::vector<std::shared_ptr<game::GameObject>> getObjects() {
147 return objects;
148 }
149
156 template <typename ObjectType>
157 std::vector<std::shared_ptr<ObjectType>> getObjectView() {
158 static_assert(std::is_base_of_v<game::GameObject, ObjectType>,
159 "ObjectType must be derived from Scene<T>");
160
161 std::vector<std::shared_ptr<ObjectType>> result;
162 for (const auto& obj : objects) {
163 if (auto castedObj = std::dynamic_pointer_cast<ObjectType>(obj)) {
164 result.push_back(castedObj);
165 }
166 }
167 return result;
168 }
169
170 protected:
173
174 private:
176 std::vector<std::shared_ptr<game::GameObject>> objects;
177
179 std::vector<std::shared_ptr<game::GameObject>> objectsToCreate;
180 };
181
188 template <typename T>
190 public:
194#ifdef __EMSCRIPTEN__
195 instance = this;
196 em_time = std::chrono::high_resolution_clock::now();
197#endif
198 }
199
205 template <typename SceneType, typename... Args>
206 void registerScene(const T sceneId, Args&&... args) {
207 static_assert(std::is_base_of_v<Scene<T>, SceneType>,
208 "SceneType must be derived from Scene<T>");
209 static_assert(std::is_constructible_v<SceneType, Args...>,
210 "SceneType must be constructible with the given arguments");
211
212 auto scene = std::make_shared<SceneType>(std::forward<Args>(args)...);
213 scenes[sceneId] = scene;
214 }
215
220 void setNextScene(const T sceneId) {
221 nextScene = sceneId;
222 hasNextScene = true;
223 }
224
231 void start() {
232#ifdef __EMSCRIPTEN__
233 emscripten_set_main_loop(SceneManager::loopEmscripten, 0, 1);
234#else
235
236 std::chrono::nanoseconds lag(0ns);
237 auto time_start = std::chrono::high_resolution_clock::now();
238 auto last_second = std::chrono::high_resolution_clock::now();
239 int frames = 0;
240
241 while (!asw::core::exit) {
242 auto delta_time =
243 std::chrono::high_resolution_clock::now() - time_start;
244 time_start = std::chrono::high_resolution_clock::now();
245 lag += std::chrono::duration_cast<std::chrono::nanoseconds>(delta_time);
246
247 while (lag >= timestep) {
248 update(timestep / 1ms);
249 lag -= timestep;
250 }
251
252 // Draw
253 draw();
254
255 frames++;
256
257 if (std::chrono::high_resolution_clock::now() - last_second >= 1s) {
258 fps = frames;
259 frames = 0;
260 last_second = last_second + 1s;
261 }
262 }
263#endif
264 }
265
268 void update(const float deltaTime) {
270 changeScene();
271
272 if (activeScene != nullptr) {
273 activeScene->update(deltaTime);
274 }
275 }
276
279 void draw() {
280 if (activeScene != nullptr) {
282 activeScene->draw();
284 }
285 }
286
291 int getFPS() const { return fps; }
292
293 private:
296 void changeScene() {
297 if (!hasNextScene) {
298 return;
299 }
300
301 if (activeScene != nullptr) {
302 activeScene->cleanup();
303 }
304
305 if (auto it = scenes.find(nextScene); it != scenes.end()) {
306 activeScene = it->second;
307 activeScene->init();
308 }
309
310 hasNextScene = false;
311 }
312
314 std::shared_ptr<Scene<T>> activeScene;
315
318
320 bool hasNextScene{false};
321
323 std::unordered_map<T, std::shared_ptr<Scene<T>>> scenes;
324
326 int fps{0};
327
328#ifdef __EMSCRIPTEN__
330 static SceneManager<T>* instance;
331
333 static std::chrono::high_resolution_clock::time_point em_time;
334
336 static void loopEmscripten() {
337 if (instance != nullptr) {
338 auto delta_time =
339 std::chrono::high_resolution_clock::now() - SceneManager::em_time;
340 SceneManager::em_time = std::chrono::high_resolution_clock::now();
341
342 instance->update(delta_time / 1ms);
343 instance->draw();
344 }
345 }
346#endif
347 };
348
349#ifdef __EMSCRIPTEN__
350 template <typename T>
351 SceneManager<T>* SceneManager<T>::instance = nullptr;
352
353 // Start time
354 template <typename T>
355 auto SceneManager<T>::em_time = std::chrono::high_resolution_clock::now();
356
357#endif
358
359} // namespace asw::scene
360
361#endif // ASW_SCENE_H
Forward declaration of the SceneManager class.
Definition scene.h:189
bool hasNextScene
Flag to indicate if there is a next scene to change to.
Definition scene.h:320
int getFPS() const
Get the current FPS. Only applies to the managed loop.
Definition scene.h:291
T nextScene
The next scene of the scene engine.
Definition scene.h:317
void changeScene()
Change the current scene to the next scene.
Definition scene.h:296
void start()
Main loop for the scene engine. If this is not enough, or you want to define your own loop,...
Definition scene.h:231
void registerScene(const T sceneId, Args &&... args)
Register a scene to be managed by the scene engine.
Definition scene.h:206
SceneManager()
Constructor for the SceneManager class.
Definition scene.h:193
void draw()
Draw the current scene.
Definition scene.h:279
std::unordered_map< T, std::shared_ptr< Scene< T > > > scenes
Collection of all scenes registered in the scene engine.
Definition scene.h:323
void setNextScene(const T sceneId)
Set the next scene.
Definition scene.h:220
int fps
@breif FPS Counter for managed loop;
Definition scene.h:326
std::shared_ptr< Scene< T > > activeScene
The current scene of the scene engine.
Definition scene.h:314
void update(const float deltaTime)
Update the current scene.
Definition scene.h:268
Base class for game scenes.
Definition scene.h:42
virtual void update(float deltaTime)
Update the game scene.
Definition scene.h:66
virtual void draw()
Draw the game scene.
Definition scene.h:95
SceneManager< T > & sceneManager
Reference to the scene manager.
Definition scene.h:172
std::vector< std::shared_ptr< game::GameObject > > getObjects()
Get game objects in the scene.
Definition scene.h:146
Scene(SceneManager< T > &sceneManager)
Constructor for the Scene class.
Definition scene.h:48
virtual void init()
Initialize the game scene.
Definition scene.h:59
virtual void cleanup()
Handle input for the game scene.
Definition scene.h:115
std::shared_ptr< ObjectType > createObject(Args &&... args)
Create a new game object in the scene.
Definition scene.h:130
std::vector< std::shared_ptr< ObjectType > > getObjectView()
Get game objects of a specific type in the scene.
Definition scene.h:157
void registerObject(const std::shared_ptr< game::GameObject > obj)
Add a game object to the scene.
Definition scene.h:121
std::vector< std::shared_ptr< game::GameObject > > objectsToCreate
Objects to be created in the next frame.
Definition scene.h:179
virtual ~Scene()=default
Destructor for the Scene class.
std::vector< std::shared_ptr< game::GameObject > > objects
Collection of game objects in the scene.
Definition scene.h:176
Core routines including main loop and initialization.
Display and window routines for the ASW library.
bool exit
When set to true, exits the main loop.
Definition core.cpp:13
void update()
Updates core module functionality.
Definition core.cpp:15
void present()
Present the window.
Definition display.cpp:69
void clear()
Clear the window.
Definition display.cpp:65
constexpr auto timestep
The time step for the game loop.
Definition scene.h:30