R-Type
Distributed multiplayer game engine in C++
Loading...
Searching...
No Matches
SpawnSystem.cpp
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2025
3** RTYPE
4** File description:
5** SpawnSystem
6*/
7
8#include "SpawnSystem.hpp"
19
20namespace ecs {
22
23 void SpawnSystem::update(Registry &registry, float deltaTime) {
24 auto spawners = registry.view<Spawner>();
25
26 // Process wave timing and spawning logic
27 for (auto spawner : spawners) {
28 Spawner &spawnerComp = registry.getComponent<Spawner>(spawner);
29
30 if (spawnerComp.getConfig().waves.empty() || !spawnerComp.isActive) {
31 continue; // No waves configured or spawner inactive
32 }
33
34 SpawnerConfig &config = spawnerComp.getConfigMutable();
35 int wavesCount = static_cast<int>(config.waves.size());
36
37 // Check if wavesIntervals is properly configured
38 if (config.wavesIntervals.empty() ||
39 spawnerComp.currentWaveIndex >= static_cast<int>(config.wavesIntervals.size())) {
40 LOG_WARNING("[SpawnSystem] Invalid wave configuration - missing intervals");
41 continue;
42 }
43
44 if (spawnerComp.currentWaveIndex >= wavesCount) {
45 spawnerComp.isActive = false;
46 continue;
47 }
48
49 // Get current wave
50 WaveConfig &currentWave = config.waves[spawnerComp.currentWaveIndex];
51 float waveInterval = static_cast<float>(config.wavesIntervals[spawnerComp.currentWaveIndex]);
52
53 // Update wave elapsed time
54 spawnerComp.waveElapsedTime += deltaTime;
55
56 // Spawn enemies FIRST based on their individual delay within the wave
57 for (auto &enemy : currentWave.enemies) {
58 if (!enemy.hasSpawned && spawnerComp.waveElapsedTime >= enemy.spawnDelay) {
59 _spawnEnemy(registry, enemy);
60 enemy.hasSpawned = true;
61 }
62 }
63
64 // THEN check if it's time to advance to next wave
65 if (spawnerComp.waveElapsedTime >= waveInterval) {
66 // Check if all enemies in current wave have spawned
67 bool allSpawned = true;
68 for (const auto &enemy : currentWave.enemies) {
69 if (!enemy.hasSpawned) {
70 allSpawned = false;
71 break;
72 }
73 }
74
75 if (allSpawned) {
76 spawnerComp.currentWaveIndex++;
77 spawnerComp.waveElapsedTime = 0.0f;
78 LOG_INFO("[SpawnSystem] Moving to wave ", spawnerComp.currentWaveIndex + 1);
79
80 if (spawnerComp.currentWaveIndex >= wavesCount) {
81 spawnerComp.isActive = false;
82 LOG_INFO("[SpawnSystem] All waves completed for this spawner.");
83 } else {
84 // Reset hasSpawned flags for the next wave
85 WaveConfig &nextWave = config.waves[spawnerComp.currentWaveIndex];
86 for (auto &enemy : nextWave.enemies) {
87 enemy.hasSpawned = false;
88 }
89 }
90 }
91 }
92 }
93 }
94
95 void SpawnSystem::_spawnEnemy(Registry &registry, const SpawnRequest &request) {
96 try {
97 Address enemy = registry.newEntity();
98
99 // Map enemy type string to numeric type
100 int enemyType = 0; // Default: basic
101 float speed = 150.0f;
102 float colliderWidth = 40.0f;
103 float colliderHeight = 40.0f;
104
105 if (request.enemyType == "basic") {
106 enemyType = 0;
107 speed = 150.0f;
108 colliderWidth = 40.0f;
109 colliderHeight = 40.0f;
110 } else if (request.enemyType == "advanced" || request.enemyType == "heavy") {
111 enemyType = 1;
112 speed = 100.0f;
113 colliderWidth = 60.0f;
114 colliderHeight = 60.0f;
115 } else if (request.enemyType == "fast") {
116 enemyType = 2;
117 speed = 200.0f;
118 colliderWidth = 30.0f;
119 colliderHeight = 30.0f;
120 } else if (request.enemyType == "boss") {
121 enemyType = 3;
122 speed = 120.0f;
123 colliderWidth = 80.0f;
124 colliderHeight = 80.0f;
125 }
126
127 registry.setComponent<Transform>(enemy, Transform(request.x, request.y));
128 registry.setComponent<Velocity>(enemy, Velocity(-1.0f, 0.0f, speed));
129 registry.setComponent<Health>(
130 enemy, Health(static_cast<int>(request.health), static_cast<int>(request.health)));
131 registry.setComponent<Enemy>(enemy, Enemy(enemyType, request.scoreValue));
132 registry.setComponent<Collider>(
133 enemy, Collider(colliderWidth, colliderHeight, 0.0f, 0.0f, 2, 0xFFFFFFFF, false));
134 registry.setComponent<Weapon>(enemy,
135 Weapon(0.33f, 2.0f, 1, 30)); // ~1 shot per 3s, type 1, 15 damage
136
137 if (!request.scriptPath.empty()) {
138 registry.setComponent<LuaScript>(enemy, LuaScript(request.scriptPath));
139 }
140
141 } catch (const std::exception &e) {
142 LOG_ERROR("[SpawnSystem] Failed to spawn enemy: ", e.what());
143 }
144 }
145
147 return 0;
148 }
149} // namespace ecs
#define LOG_INFO(...)
Definition Logger.hpp:181
#define LOG_ERROR(...)
Definition Logger.hpp:183
#define LOG_WARNING(...)
Definition Logger.hpp:182
Component for collision detection and physics interactions.
Definition Collider.hpp:21
Component identifying an entity as an enemy with AI behavior.
Definition Enemy.hpp:20
Component representing entity health and invincibility.
Definition Health.hpp:20
Component that holds the path to a Lua script for entity behavior.
Definition LuaScript.hpp:21
Manages entities, their signatures and component type registrations.
Definition Registry.hpp:68
Address newEntity()
Create and register a new entity, returning its Address.
Definition Registry.cpp:47
T & getComponent(Address address)
Get a component from an entity.
std::vector< Address > view()
Get all entities that have a specific set of components.
void setComponent(Address address, const T &component)
Set/add a component to an entity with its data.
SpawnSystem()
Constructs a SpawnSystem with default wave configuration.
void _spawnEnemy(Registry &registry, const SpawnRequest &request)
Internal method to spawn an enemy from a request.
ComponentMask getComponentMask() const override
Gets the component mask for this system.
void update(Registry &registry, float deltaTime) override
Manages entity spawning based on wave progression.
Component that holds spawn requests to be processed by SpawnSystem.
Definition Spawner.hpp:48
const SpawnerConfig & getConfig() const
Definition Spawner.hpp:95
int currentWaveIndex
Definition Spawner.hpp:99
SpawnerConfig & getConfigMutable()
Definition Spawner.hpp:96
float waveElapsedTime
Definition Spawner.hpp:98
Component representing position, rotation and scale in 2D space.
Definition Transform.hpp:20
Component representing movement direction and speed.
Definition Velocity.hpp:20
Component for entities capable of shooting projectiles.
Definition Weapon.hpp:28
Maximum number of distinct component types supported by the Registry.
Definition GameLogic.hpp:26
std::uint32_t Address
Type used to represent an entity address/ID.
std::uint64_t ComponentMask
Type alias for component bitmask.
Definition ISystem.hpp:24
Declarative request for spawning an entity.
Definition Spawner.hpp:19
std::string scriptPath
Definition Spawner.hpp:23
std::string enemyType
Definition Spawner.hpp:22
std::vector< WaveConfig > waves
Definition Spawner.hpp:36
std::vector< int > wavesIntervals
Definition Spawner.hpp:37
std::vector< SpawnRequest > enemies
Definition Spawner.hpp:31