Air-Trap 1.0.0
A multiplayer R-Type clone game engine built with C++23 and ECS architecture
Loading...
Searching...
No Matches
EntitySystem.cpp
Go to the documentation of this file.
1
11
12namespace rtp::server
13{
15 // Public API
17
19 ServerNetwork &network,
20 NetworkSyncSystem &networkSync)
21 : _registry(registry)
22 , _network(network)
23 , _networkSync(networkSync)
24 {
25 }
26
27 void EntitySystem::update(float dt)
28 {
29 (void)dt;
30 }
31
33 {
34 return createPlayerEntity(player, {100.f, 100.f});
35 }
36
39 const Vec2f &spawnPos)
40 {
41 auto entityRes = _registry.spawn();
42 if (!entityRes) {
43 log::error("Failed to spawn player entity: {}",
44 entityRes.error().message());
45 throw std::runtime_error(
46 std::string("Failed to spawn player entity: ") +
47 std::string(entityRes.error().message()));
48 }
49
50 ecs::Entity entity = entityRes.value();
51
54 {spawnPos.x, spawnPos.y},
55 0.f,
56 {1.f, 1.f }
57 });
58
61 {0.f, 0.f},
62 0.f
63 });
64
66 auto weaponKind = player->getWeaponKind();
67 weapon.kind = weaponKind;
68
70 weapon = rtp::config::getWeaponDef(weaponKind);
71 weapon.kind = weaponKind;
72 } else {
73 log::warning("Weapon configurations not found, using default weapon settings for kind {}", static_cast<int>(weaponKind));
74 }
75
77
78 ecs::components::Ammo ammoComp{};
79 if (weapon.maxAmmo >= 0) {
80 ammoComp.max = static_cast<uint16_t>(weapon.maxAmmo);
81 ammoComp.current = static_cast<uint16_t>(weapon.ammo > 0 ? weapon.ammo : weapon.maxAmmo);
82 } else {
83 ammoComp.max = 0;
84 ammoComp.current = 0;
85 }
86 // Use weapon-specific reload/cooldown when appropriate (Beam uses beamCooldown)
87 if (weapon.kind == ecs::components::WeaponKind::Beam) {
88 ammoComp.reloadCooldown = weapon.beamCooldown;
89 } else {
90 ammoComp.reloadCooldown = 2.0f;
91 }
92 ammoComp.reloadTimer = 0.0f;
93 ammoComp.isReloading = false;
94 ammoComp.dirty = true;
95
97 entity,
98 ammoComp);
99
101 entity, ecs::components::MovementSpeed{200.0f, 1.0f, 0.0f});
102
104 entity, ecs::components::NetworkId{(uint32_t)entity});
105
108
110 entity,
112
114 entity, ecs::components::Health{100, 100});
115
117 entity, ecs::components::BoundingBox{32.0f, 16.0f});
118
120 entity, ecs::components::RoomId{player->getRoomId()});
121
122 return entity;
123 }
124
126 {
128 wcfg.kind = weaponKind;
129
131 wcfg = rtp::config::getWeaponDef(weaponKind);
132 wcfg.kind = weaponKind;
133 } else {
134 log::warning("Weapon configurations not found, using default weapon settings for kind {}", static_cast<int>(weaponKind));
135 }
136
137 auto weaponRes = _registry.get<ecs::components::SimpleWeapon>();
138 if (weaponRes) {
139 auto &weapons = weaponRes->get();
140 if (weapons.has(entity)) {
141 weapons[entity] = wcfg;
142 } else {
144 }
145 } else {
147 }
148
149 auto ammoRes = _registry.get<ecs::components::Ammo>();
150 if (ammoRes) {
151 auto &ammos = ammoRes->get();
152 if (ammos.has(entity) && wcfg.maxAmmo >= 0) {
153 ammos[entity].max = static_cast<uint16_t>(wcfg.maxAmmo);
154 ammos[entity].current = static_cast<uint16_t>(wcfg.ammo > 0 ? wcfg.ammo : ammos[entity].current);
155 }
156 // Update reload cooldown if this is a Beam weapon
157 if (ammos.has(entity)) {
159 ammos[entity].reloadCooldown = wcfg.beamCooldown;
160 }
161 }
162 }
163
164 log::info("Applied weapon {} to entity {}", static_cast<int>(weaponKind), entity.index());
165 }
166
168 uint32_t roomId, const Vec2f &pos,
169 ecs::components::Patterns pattern, float speed, float amplitude,
170 float frequency, net::EntityType type)
171 {
172 auto entityRes = _registry.spawn();
173 if (!entityRes) {
174 log::error("Failed to spawn enemy entity: {}",
175 entityRes.error().message());
176 throw std::runtime_error(
177 std::string("Failed to spawn enemy entity: ") +
178 std::string(entityRes.error().message()));
179 }
180
181 ecs::Entity entity = entityRes.value();
182
185 {pos.x, pos.y},
186 0.f,
187 {1.f, 1.f }
188 });
189
192 static_cast<uint32_t>(entity.index())});
193
195 entity, ecs::components::EntityType{type});
196
198 entity, ecs::components::RoomId{roomId});
199
200 int maxHealth = 40;
201 if (type == net::EntityType::Tank) {
202 maxHealth = 80;
203 } else if (type == net::EntityType::Boss) {
204 maxHealth = 500;
205 } else if (type == net::EntityType::Boss2) {
206 maxHealth = 800; // Kraken is tougher!
207 } else if (type == net::EntityType::BossShield) {
208 maxHealth = 150;
209 }
211 entity, ecs::components::Health{maxHealth, maxHealth});
212
215 {0.f, 0.f},
216 0.f
217 });
218
221 pattern, speed, amplitude, frequency});
222
223 float fireRate = 0.6f;
224 if (type == net::EntityType::Tank) {
225 fireRate = 0.4f;
226 } else if (type == net::EntityType::Boss) {
227 fireRate = 1.2f;
228 } else if (type == net::EntityType::Boss2) {
229 fireRate = 0.8f; // Kraken shoots faster boomerangs
230 }
233 if (type == net::EntityType::Boss2) {
234 enemyWeapon.isBoomerang = true; // Kraken shoots boomerangs!
235 }
236 enemyWeapon.fireRate = fireRate;
237 enemyWeapon.lastShotTime = 0.0f;
238 enemyWeapon.damage = 0;
239 _registry.add<ecs::components::SimpleWeapon>(entity, enemyWeapon);
240
241 float bboxWidth = 30.0f;
242 float bboxHeight = 18.0f;
243
244 if (type == net::EntityType::Boss) {
245 bboxWidth = 198.0f;
246 bboxHeight = 198.0f;
247 } else if (type == net::EntityType::Boss2) {
248 bboxWidth = 350.0f; // Kraken is huge!
249 bboxHeight = 180.0f;
250 } else if (type == net::EntityType::BossShield) {
251 bboxWidth = 90.0f;
252 bboxHeight = 99.0f;
253 }
254
256 entity, ecs::components::BoundingBox{bboxWidth, bboxHeight});
257
258 // _registry.add<ecs::components::IABehaviorComponent>(
259 // entity,
260 // ecs::components::IABehaviorComponent{
261 // ecs::components::IABehavior::Passive, 500.0 }
262 // );
263
264 return entity;
265 }
266
268 EntitySystem::creaetEnemyEntity(uint32_t roomId, const Vec2f &pos,
270 float speed, float amplitude,
271 float frequency)
272 {
273 return createEnemyEntity(roomId, pos, pattern, speed, amplitude,
274 frequency, net::EntityType::Scout);
275 }
276
278 uint32_t roomId, const Vec2f &pos,
279 ecs::components::PowerupType type, float value, float duration)
280 {
281 auto entityRes = _registry.spawn();
282 if (!entityRes) {
283 log::error("Failed to spawn powerup entity: {}",
284 entityRes.error().message());
285 throw std::runtime_error(
286 std::string("Failed to spawn powerup entity: ") +
287 std::string(entityRes.error().message()));
288 }
289
290 ecs::Entity entity = entityRes.value();
291
294 {pos.x, pos.y},
295 0.f,
296 {1.f, 1.f }
297 });
298
299 const net::EntityType netType =
303
305 entity, ecs::components::EntityType{netType});
306
308 entity, ecs::components::Powerup{type, value, duration});
309
311 entity, ecs::components::BoundingBox{16.0f, 16.0f});
312
315 static_cast<uint32_t>(entity.index())});
316
318 entity, ecs::components::RoomId{roomId});
319
320 return entity;
321 }
322
324 uint32_t roomId, const Vec2f &pos, const Vec2f &size,
325 int health, net::EntityType type)
326 {
327 auto entityRes = _registry.spawn();
328 if (!entityRes) {
329 log::error("Failed to spawn obstacle entity: {}",
330 entityRes.error().message());
331 throw std::runtime_error(
332 std::string("Failed to spawn obstacle entity: ") +
333 std::string(entityRes.error().message()));
334 }
335
336 ecs::Entity entity = entityRes.value();
337
340 {pos.x, pos.y},
341 0.f,
342 {1.f, 1.f }
343 });
344
346 entity, ecs::components::EntityType{type});
347
349 entity, ecs::components::Health{health, health});
350
352 entity, ecs::components::BoundingBox{size.x, size.y});
353
356 static_cast<uint32_t>(entity.index())});
357
359 entity, ecs::components::RoomId{roomId});
360
361 return entity;
362 }
363} // namespace rtp::server
Represents an entity in the ECS (Entity-Component-System) architecture.
Definition Entity.hpp:63
constexpr std::uint32_t index(void) const
auto spawn(void) -> std::expected< Entity, rtp::Error >
Definition Registry.cpp:51
auto add(Entity entity, Args &&...args) -> std::expected< std::reference_wrapper< T >, rtp::Error >
auto get(this const Self &self) -> std::expected< std::reference_wrapper< ConstLike< Self, SparseArray< T > > >, rtp::Error >
void update(float dt) override
Update movement system logic for one frame.
ecs::Entity creaetEnemyEntity(uint32_t roomId, const Vec2f &pos, ecs::components::Patterns pattern, float speed, float amplitude, float frequency)
Create a new enemy entity in the ECS with default type Scout.
ecs::Entity createObstacleEntity(uint32_t roomId, const Vec2f &pos, const Vec2f &size, int health, net::EntityType type=net::EntityType::Obstacle)
Create a new obstacle entity in the ECS.
ecs::Entity createPlayerEntity(PlayerPtr player)
Create a new player entity in the ECS.
EntitySystem(ecs::Registry &registry, ServerNetwork &network, NetworkSyncSystem &networkSync)
Constructor for EntitySystem.
void applyWeaponToEntity(ecs::Entity entity, ecs::components::WeaponKind weaponKind)
Apply a weapon configuration to an existing entity (player)
ecs::Entity createEnemyEntity(uint32_t roomId, const Vec2f &pos, ecs::components::Patterns pattern, float speed, float amplitude, float frequency, net::EntityType type=net::EntityType::Scout)
Create a new enemy entity in the ECS.
ecs::Entity createPowerupEntity(uint32_t roomId, const Vec2f &pos, ecs::components::PowerupType type, float value, float duration)
Create a new powerup entity in the ECS.
ecs::Registry & _registry
Reference to the entity registry.
System to handle network-related operations on the server side.
Implementation ASIO du serveur réseau (TCP + UDP)
bool hasWeaponConfigs()
const rtp::ecs::components::SimpleWeapon & getWeaponDef(rtp::ecs::components::WeaponKind kind)
WeaponKind
Types of player weapons.
@ Classic
Default spam/charge laser.
@ Beam
Continuous beam 5s active, 5s cooldown.
Patterns
Enum representing different enemy movement patterns.
PowerupType
Supported powerup types.
Definition Powerup.hpp:16
void error(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an error message.
void warning(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log a warning message.
void info(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an informational message.
EntityType
Types of entities in the game.
Definition Packet.hpp:144
File : GameManager.hpp License: MIT Author : Elias Josué HAJJAR LLAUQUEN elias-josue....
std::shared_ptr< Player > PlayerPtr
Shared pointer type for Player.
Definition Player.hpp:178
Ammo tracking for weapons.
Definition Ammo.hpp:18
Component representing an entity's health.
Definition Health.hpp:15
Component representing a movement pattern.
Component representing movement speed with temporary boosts.
Component representing a network identifier for an entity.
Definition NetworkId.hpp:22
Component representing a powerup pickup.
Definition Powerup.hpp:27
Component representing a network identifier for an entity.
Definition RoomId.hpp:22
Component representing a weapon configuration.
float beamCooldown
Beam cooldown time (Beam)
int maxAmmo
Max ammo (-1 = infinite)
bool isBoomerang
Projectile returns (Boomerang)
int ammo
Current ammo (-1 = infinite)
float fireRate
Shots per second (or cooldown)
float lastShotTime
Time since last shot.
Component representing position, rotation, and scale of an entity.
Definition Transform.hpp:23
Component representing a 2D velocity.
Definition Velocity.hpp:17
Component to handle network input for server entities.