r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
EnemySpawnSystem.cpp
Go to the documentation of this file.
1///
2/// @file EnemySpawnSystem.cpp
3/// @brief Implementation of enemy spawning system
4/// @namespace gme
5///
6
8#include "Utils/Logger.hpp"
9#include <chrono>
10
11namespace gme
12{
14 : m_entityManager(entityManager), m_levelTime(0.0f), m_currentWaveIndex(0), m_waveSpawnTimer(0.0f),
15 m_enabled(false), m_totalEnemiesSpawned(0), m_yDistribution(100.0f, 980.0f)
16 {
17 const auto seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
18 m_rng.seed(seed);
19
21
22 utl::Logger::log("EnemySpawnSystem: Initialized with " + std::to_string(m_waves.size()) + " waves",
24 }
25
26 void EnemySpawnSystem::update(ecs::Registry &registry, float deltaTime)
27 {
28 (void)registry; // Use member entityManager instead
29 if (!m_enabled)
30 return;
31
32 m_levelTime += deltaTime;
33 m_waveSpawnTimer += deltaTime;
34
35 // Check if we should process current wave
36 if (m_currentWaveIndex < m_waves.size())
37 {
38 auto &wave = m_waves[m_currentWaveIndex];
39
40 // Check if it's time to start this wave
41 if (m_levelTime >= wave.spawnTime)
42 {
43 processWave(wave, deltaTime);
44
45 // Check if wave is complete
46 int totalToSpawn = wave.basicEnemyCount + wave.advancedEnemyCount + (wave.bossSpawn ? 1 : 0);
47 if (wave.spawnedCount >= totalToSpawn)
48 {
49 // Move to next wave
51 m_waveSpawnTimer = 0.0f;
52
53 if (m_currentWaveIndex < m_waves.size())
54 {
55 utl::Logger::log("EnemySpawnSystem: Wave " + std::to_string(m_currentWaveIndex) +
56 " complete. Moving to wave " + std::to_string(m_currentWaveIndex + 1),
58 }
59 else
60 {
61 utl::Logger::log("EnemySpawnSystem: All waves complete!", utl::LogLevel::INFO);
62 }
63 }
64 }
65 }
66 }
67
69 {
70 m_levelTime = 0.0f;
72 m_waveSpawnTimer = 0.0f;
74 m_enabled = false;
75
76 // Reset wave spawn counts
77 for (auto &wave : m_waves)
78 {
79 wave.spawnedCount = 0;
80 }
81
82 utl::Logger::log("EnemySpawnSystem: Reset", utl::LogLevel::INFO);
83 }
84
86 {
87 m_waves.clear();
88
89 // Wave 1: 5 basic enemies (10 seconds in, 1 enemy every 1 second)
90 SpawnWave wave1;
91 wave1.spawnTime = 10.0f;
92 wave1.basicEnemyCount = 5;
93 wave1.advancedEnemyCount = 0;
94 wave1.bossSpawn = false;
95 wave1.spawnInterval = 1.0f;
96 wave1.spawnedCount = 0;
97 m_waves.push_back(wave1);
98
99 // Wave 2: 3 basic + 2 advanced (20 seconds in, 1 enemy every 1.5 seconds)
100 SpawnWave wave2;
101 wave2.spawnTime = 20.0f;
102 wave2.basicEnemyCount = 3;
103 wave2.advancedEnemyCount = 2;
104 wave2.bossSpawn = false;
105 wave2.spawnInterval = 1.5f;
106 wave2.spawnedCount = 0;
107 m_waves.push_back(wave2);
108
109 // Wave 3: 2 basic + 4 advanced (35 seconds in, 1 enemy every 1.2 seconds)
110 SpawnWave wave3;
111 wave3.spawnTime = 35.0f;
112 wave3.basicEnemyCount = 2;
113 wave3.advancedEnemyCount = 4;
114 wave3.bossSpawn = false;
115 wave3.spawnInterval = 1.2f;
116 wave3.spawnedCount = 0;
117 m_waves.push_back(wave3);
118
119 // Wave 4: 7 advanced enemies (55 seconds in, 1 enemy every 2 seconds)
120 SpawnWave wave4;
121 wave4.spawnTime = 55.0f;
122 wave4.basicEnemyCount = 0;
123 wave4.advancedEnemyCount = 7;
124 wave4.bossSpawn = false;
125 wave4.spawnInterval = 2.0f;
126 wave4.spawnedCount = 0;
127 m_waves.push_back(wave4);
128
129 // Wave 5: Boss (80 seconds in)
130 SpawnWave wave5;
131 wave5.spawnTime = 80.0f;
132 wave5.basicEnemyCount = 0;
133 wave5.advancedEnemyCount = 0;
134 wave5.bossSpawn = true;
135 wave5.spawnInterval = 0.0f;
136 wave5.spawnedCount = 0;
137 m_waves.push_back(wave5);
138 }
139
140 void EnemySpawnSystem::processWave(SpawnWave &wave, float deltaTime)
141 {
142 (void)deltaTime; // Not used directly, but kept for consistency
143
144 int totalToSpawn = wave.basicEnemyCount + wave.advancedEnemyCount + (wave.bossSpawn ? 1 : 0);
145
146 // Check if we've spawned everything for this wave
147 if (wave.spawnedCount >= totalToSpawn)
148 return;
149
150 // Check if enough time has passed since last spawn
152 return;
153
154 // Spawn next enemy
155 float spawnX = getSpawnX();
156 float spawnY = getRandomY();
157
158 // Determine which type to spawn based on what's left
159 if (wave.bossSpawn && wave.spawnedCount == 0)
160 {
161 // Spawn boss first if this is a boss wave
162 m_entityManager.createBoss(spawnX, spawnY, 1000.0f);
164 wave.spawnedCount++;
165
166 utl::Logger::log("EnemySpawnSystem: Spawned BOSS at (" + std::to_string(spawnX) + ", " +
167 std::to_string(spawnY) + ")",
169 }
170 else if (wave.basicEnemyCount > 0 && wave.spawnedCount < wave.basicEnemyCount)
171 {
172 // Spawn basic enemy
173 m_entityManager.createBasicEnemy(spawnX, spawnY, 50.0f);
175 wave.spawnedCount++;
176
177 utl::Logger::log("EnemySpawnSystem: Spawned basic enemy at (" + std::to_string(spawnX) + ", " +
178 std::to_string(spawnY) + ")",
180 }
181 else if (wave.advancedEnemyCount > 0)
182 {
183 // Spawn advanced enemy
184 m_entityManager.createAdvancedEnemy(spawnX, spawnY, 100.0f);
186 wave.spawnedCount++;
187
188 utl::Logger::log("EnemySpawnSystem: Spawned advanced enemy at (" + std::to_string(spawnX) + ", " +
189 std::to_string(spawnY) + ")",
191 }
192
193 // Reset spawn timer
194 m_waveSpawnTimer = 0.0f;
195 }
196
198 {
199 // Return a random Y position within screen bounds
200 // Screen height is 1080, so we spawn between 100 and 980 to leave margins
201 return m_yDistribution(m_rng);
202 }
203
204} // namespace gme
Server-side enemy spawning system for R-Type game progression.
This file contains the Logger class.
Class for managing entities and their components.
Definition Registry.hpp:25
std::mt19937 m_rng
Random number generator for spawn positions.
void processWave(SpawnWave &wave, float deltaTime)
Process a single spawn wave.
void initializeWaves()
Initialize all spawn waves for the level.
EntityManager & m_entityManager
Entity manager for spawning enemies.
size_t m_currentWaveIndex
Index of current/next wave to process.
EnemySpawnSystem(EntityManager &entityManager)
Constructor.
void reset()
Reset the spawn system to initial state.
void update(ecs::Registry &registry, float deltaTime) override
Update the spawn system (called each frame)
float m_waveSpawnTimer
Timer for spawning enemies within current wave.
bool m_enabled
Whether spawning is currently enabled.
float m_levelTime
Elapsed time since level start (seconds)
std::vector< SpawnWave > m_waves
List of all spawn waves for the level.
std::uniform_real_distribution< float > m_yDistribution
Distribution for random Y positions.
float getRandomY()
Generate random Y position for enemy spawn.
size_t m_totalEnemiesSpawned
Total number of enemies spawned this session.
float getSpawnX() const
Get X position for enemy spawns (right side of screen)
Central entity lifecycle manager for the R-Type game server.
ecs::Entity createBoss(float x, float y, float health=1000.0f)
Create a boss enemy entity.
ecs::Entity createAdvancedEnemy(float x, float y, float health=100.0f)
Create an advanced enemy entity.
ecs::Entity createBasicEnemy(float x, float y, float health=50.0f)
Create a basic enemy entity.
static void log(const std::string &message, const LogLevel &logLevel)
Definition Logger.hpp:51
Configuration data for a single enemy spawn wave.
bool bossSpawn
Whether this wave spawns a boss enemy.
float spawnInterval
Time between individual enemy spawns within wave (seconds)
int basicEnemyCount
Number of basic enemies to spawn in this wave.
int spawnedCount
Number of enemies already spawned from this wave (internal counter)
int advancedEnemyCount
Number of advanced enemies to spawn in this wave.
float spawnTime
Time from level start when wave begins (seconds)