-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathplay-state.hpp
More file actions
166 lines (146 loc) · 6.58 KB
/
Copy pathplay-state.hpp
File metadata and controls
166 lines (146 loc) · 6.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#pragma once
#include <application.hpp>
#include <asset-loader.hpp>
#include <components/camera.hpp>
#include <components/player.hpp>
#include <ecs/world.hpp>
#include <systems/audio-system.hpp>
#include <systems/collision-system.hpp>
#include <systems/enemy-ai.hpp>
#include <systems/enemy-health-bar.hpp>
#include <systems/enemy-spawner.hpp>
#include <systems/forward-renderer.hpp>
#include <systems/free-camera-controller.hpp>
#include <systems/movement.hpp>
#include <systems/ui-renderer.hpp>
// This state shows how to use the ECS framework and deserialization.
class Playstate : public our::State {
our::World world;
our::ForwardRenderer renderer;
our::UIRenderer uiRenderer;
our::FreeCameraControllerSystem cameraController;
our::MovementSystem movementSystem;
ALuint reloadSource = 0; // TODO: remove when implementing a proper weapon/player system
gameplay::CollisionSystem collisionSystem;
our::Entity* playerEntity = nullptr;
our::CameraComponent* activeCamera = nullptr;
gameplay::EnemyAISystem enemyAI;
gameplay::EnemySpawner enemySpawner;
gameplay::EnemyHealthBarSystem enemyHealthBars;
void displayFPS() const {
// Pin a transparent overlay window to the top-left corner
ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_Always);
// Red if below 120 FPS, green otherwise
float fps = ImGui::GetIO().Framerate;
ImVec4 fpsColor = (fps < 120.0f) ? ImVec4(1.0f, 0.0f, 0.0f, 1.0f) : ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
ImGuiWindowFlags textWindowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoMove;
ImGui::SetNextWindowBgAlpha(0.35f);
if (ImGui::Begin("FPS Overlay", nullptr, textWindowFlags)) {
ImGui::TextColored(fpsColor, "FPS: %.1f", fps);
}
ImGui::End();
}
void onImmediateGui() override {
displayFPS();
#ifdef COLLISION_DEBUG_DRAW
if (collisionSystem.isDebugDrawEnabled()) {
ImGui::SetNextWindowPos(ImVec2(10.0f, 40.0f), ImGuiCond_Always);
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoMove;
ImGui::SetNextWindowBgAlpha(0.35f);
if (ImGui::Begin("Debug Draw Overlay", nullptr, flags)) {
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "[F3] Collision Debug: ON");
}
ImGui::End();
}
#endif
}
void onInitialize() override {
// First of all, we get the scene configuration from the app config
auto& config = getApp()->getConfig()["scene"];
// If we have assets in the scene config, we deserialize them
if (config.contains("assets")) {
our::deserializeAllAssets(config["assets"]);
}
// If we have a world in the scene config, we use it to populate our world
if (config.contains("world")) {
world.deserialize(config["world"]);
}
activeCamera = nullptr;
playerEntity = nullptr;
for (our::Entity* entity : world.getEntities()) {
if (!activeCamera) activeCamera = entity->getComponent<our::CameraComponent>();
if (!playerEntity && entity->getComponent<gameplay::PlayerComponent>()) playerEntity = entity;
if (activeCamera && playerEntity) break;
}
// We initialize the camera controller system since it needs a pointer to the app
cameraController.enter(getApp());
// Then we initialize the renderer
auto size = getApp()->getFrameBufferSize();
renderer.initialize(size, config["renderer"]);
uiRenderer.initialize();
collisionSystem.initialize();
enemySpawner.deserialize(config);
enemySpawner.initialize(&world);
enemyHealthBars.deserialize(config);
}
void onDraw(double deltaTime) override {
float dt = static_cast<float>(deltaTime);
movementSystem.update(&world, dt);
cameraController.update(&world, dt);
getApp()->getAudioSystem().update(&world);
enemyAI.update(&world, playerEntity, dt);
enemySpawner.update(&world, dt);
collisionSystem.update(&world);
// Rendering
renderer.render(&world, getApp()->getFrameBufferSize());
enemyHealthBars.render(&world, getApp(), uiRenderer, activeCamera);
#ifdef COLLISION_DEBUG_DRAW
// Toggle debug draw with F3
auto& keyboard = getApp()->getKeyboard();
if (keyboard.justPressed(GLFW_KEY_F3)) {
collisionSystem.setDebugDrawEnabled(!collisionSystem.isDebugDrawEnabled());
}
// Draw collision wireframes after the main render pass
if (collisionSystem.isDebugDrawEnabled()) {
if (activeCamera) {
auto size = getApp()->getFrameBufferSize();
glm::mat4 VP = activeCamera->getProjectionMatrix(size) * activeCamera->getViewMatrix();
collisionSystem.debugDraw(VP);
}
}
#else
// Get a reference to the keyboard object
auto& keyboard = getApp()->getKeyboard();
#endif
if (keyboard.justPressed(GLFW_KEY_ESCAPE)) {
// If the escape key is pressed in this frame, go to the play state
getApp()->changeState("menu");
}
// clang-format off
if (keyboard.justPressed(GLFW_KEY_R)) {
if (!getApp()->getAudioSystem().isPlaying(reloadSource)) { // TODO: remove when implementing a proper weapon/player system
reloadSource = getApp()->getAudioSystem().playSound2D(
our::AssetLoader<our::AudioBuffer>::get("gun-reload"), 1.0f, 1.0f, false);
}
}
// clang-format on
}
void onDestroy() override {
collisionSystem.destroy();
renderer.destroy();
uiRenderer.destroy();
// On exit, we call exit for the camera controller system to make sure that the mouse is unlocked
cameraController.exit();
// Stop all audio and release resources
getApp()->getAudioSystem().stopAll();
activeCamera = nullptr;
playerEntity = nullptr;
world.clear();
// Delete all the loaded assets to free memory on the RAM and the VRAM
our::clearAllAssets();
}
};