r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
CollisionSystem.cpp
Go to the documentation of this file.
1///
2/// @file CollisionSystem.cpp
3/// @brief Implementation of server-side collision detection system
4/// @namespace gme
5///
6
8#include "Utils/Logger.hpp"
9#include <algorithm>
10
11namespace gme
12{
13 void CollisionSystem::update(ecs::Registry &registry, float deltaTime)
14 {
15 (void)registry; // Use member registry instead
16 (void)deltaTime; // Collision detection is instantaneous
17
19
20 // Check all collision types
25 }
26
28 {
29 const auto &projectiles = m_entityManager.getProjectiles();
30 const auto &enemies = m_entityManager.getEnemies();
31
32 for (const auto &[projId, projEntity] : projectiles)
33 {
34 // Check if this is a player projectile
35 const auto *projMetadata = m_entityManager.getEntityMetadata(projId);
36 if (!projMetadata || projMetadata->type != ServerEntityType::PROJECTILE_PLAYER)
37 continue;
38
39 // Skip if projectile is already marked for destruction
40 if (!projMetadata->isActive)
41 continue;
42
43 auto *projProjectile = m_registry.getComponent<ecs::Projectile>(projEntity);
44 if (!projProjectile || projProjectile->pierce_remaining <= 0)
45 continue;
46
47 float projX, projY, projRadius;
48 if (!getCollisionInfo(projEntity, projX, projY, projRadius))
49 continue;
50
51 // Check collision with all enemies
52 for (const auto &[enemyId, enemyEntity] : enemies)
53 {
54 const auto *enemyMetadata = m_entityManager.getEntityMetadata(enemyId);
55 if (!enemyMetadata || !enemyMetadata->isActive)
56 continue;
57
58 float enemyX, enemyY, enemyRadius;
59 if (!getCollisionInfo(enemyEntity, enemyX, enemyY, enemyRadius))
60 continue;
61
62 float overlapDist;
63 if (checkCircleCollision(projX, projY, projRadius, enemyX, enemyY, enemyRadius, &overlapDist))
64 {
65 // Collision detected!
67
68 // Get projectile owner for score attribution
69 std::uint32_t ownerId = projMetadata->ownerId;
70
71 // Apply damage to enemy and award score if killed
72 applyDamageToEnemy(enemyId, projProjectile->damage, ownerId);
73
74 // Reduce pierce count
75 projProjectile->pierce_remaining--;
76
77 // Collision logged only for debugging (too verbose at INFO level)
78 // utl::Logger::log("CollisionSystem: Projectile " + std::to_string(projId) + " hit enemy " +
79 // std::to_string(enemyId) + " (pierce remaining: " +
80 // std::to_string(projProjectile->pierce_remaining) + ")");
81
82 // If projectile has no more pierce, mark for destruction
83 if (projProjectile->pierce_remaining <= 0)
84 {
86 break; // Stop checking other enemies
87 }
88 }
89 }
90 }
91 }
92
94 {
95 const auto &projectiles = m_entityManager.getProjectiles();
96 const auto &players = m_entityManager.getPlayers();
97
98 for (const auto &[projId, projEntity] : projectiles)
99 {
100 // Check if this is an enemy projectile
101 const auto *projMetadata = m_entityManager.getEntityMetadata(projId);
102 if (!projMetadata || projMetadata->type != ServerEntityType::PROJECTILE_ENEMY)
103 continue;
104
105 if (!projMetadata->isActive)
106 continue;
107
108 float projX, projY, projRadius;
109 if (!getCollisionInfo(projEntity, projX, projY, projRadius))
110 continue;
111
112 auto *projProjectile = m_registry.getComponent<ecs::Projectile>(projEntity);
113 if (!projProjectile)
114 continue;
115
116 // Check collision with all players
117 for (const auto &[playerId, playerEntity] : players)
118 {
119 float playerX, playerY, playerRadius;
120 if (!getCollisionInfo(playerEntity, playerX, playerY, playerRadius))
121 continue;
122
123 if (checkCircleCollision(projX, projY, projRadius, playerX, playerY, playerRadius))
124 {
125 // Collision detected!
127
128 // Apply damage to player
129 applyDamageToPlayer(playerId, projProjectile->damage);
130
131 // Destroy projectile
133
134 // Collision logged only for debugging (too verbose at INFO level)
135 // utl::Logger::log("CollisionSystem: Enemy projectile " + std::to_string(projId) + " hit player " +
136 // std::to_string(playerId));
137
138 break; // Stop checking other players
139 }
140 }
141 }
142 }
143
145 {
146 const auto &players = m_entityManager.getPlayers();
147 const auto &enemies = m_entityManager.getEnemies();
148
149 for (const auto &[playerId, playerEntity] : players)
150 {
151 float playerX, playerY, playerRadius;
152 if (!getCollisionInfo(playerEntity, playerX, playerY, playerRadius))
153 continue;
154
155 // Check collision with all enemies
156 for (const auto &[enemyId, enemyEntity] : enemies)
157 {
158 const auto *enemyMetadata = m_entityManager.getEntityMetadata(enemyId);
159 if (!enemyMetadata || !enemyMetadata->isActive)
160 continue;
161
162 float enemyX, enemyY, enemyRadius;
163 if (!getCollisionInfo(enemyEntity, enemyX, enemyY, enemyRadius))
164 continue;
165
166 if (checkCircleCollision(playerX, playerY, playerRadius, enemyX, enemyY, enemyRadius))
167 {
168 // Collision detected!
170
171 // Get enemy damage
172 auto *enemy = m_registry.getComponent<ecs::Enemy>(enemyEntity);
173 float damage = enemy ? enemy->damage : 10.0f;
174
175 // Apply damage to player
176 applyDamageToPlayer(playerId, damage);
177
178 // Apply damage to enemy (ram damage) - no score for ram damage
179 applyDamageToEnemy(enemyId, 20.0f, 0);
180
181 // Collision logged only for debugging (too verbose at INFO level)
182 // utl::Logger::log("CollisionSystem: Player " + std::to_string(playerId) + " collided with enemy "
183 // +
184 // std::to_string(enemyId));
185 }
186 }
187 }
188 }
189
191 {
192 // TODO: Implement when powerup collection is needed
193 // For now, this is a placeholder
194 }
195
196 void CollisionSystem::applyDamageToEnemy(std::uint32_t enemyId, float damage, std::uint32_t attackerPlayerId)
197 {
198 ecs::Entity enemyEntity = m_entityManager.getEnemy(enemyId);
199 if (enemyEntity == ecs::INVALID_ENTITY)
200 return;
201
202 auto *enemy = m_registry.getComponent<ecs::Enemy>(enemyEntity);
203 if (!enemy)
204 return;
205
206 enemy->health -= damage;
207
208 // Damage logged only for debugging (too verbose at INFO level)
209 // utl::Logger::log("CollisionSystem: Enemy " + std::to_string(enemyId) + " took " + std::to_string(damage) +
210 // " damage (health: " + std::to_string(enemy->health) + "/" +
211 // std::to_string(enemy->max_health) + ")");
212
213 // Check if enemy is dead
214 if (enemy->health <= 0.0f)
215 {
216 utl::Logger::log("CollisionSystem: Enemy " + std::to_string(enemyId) + " destroyed", utl::LogLevel::INFO);
217
218 // Award score to the player who killed the enemy
219 if (attackerPlayerId > 0)
220 {
221 const auto *enemyMetadata = m_entityManager.getEntityMetadata(enemyId);
222 int points = 0;
223
224 // Different points based on enemy type
225 if (enemyMetadata)
226 {
227 switch (enemyMetadata->type)
228 {
230 points = 100;
231 break;
233 points = 250;
234 break;
236 points = 1000;
237 break;
238 default:
239 points = 50;
240 break;
241 }
242 }
243
244 m_entityManager.addScore(attackerPlayerId, points);
245 }
246
248 }
249 }
250
251 void CollisionSystem::applyDamageToPlayer(std::uint32_t playerId, float damage)
252 {
253 ecs::Entity playerEntity = m_entityManager.getPlayerEntity(playerId);
254 auto *health = m_registry.getComponent<ecs::Health>(playerEntity);
255
256 if (!health)
257 {
258 utl::Logger::log("CollisionSystem: Player " + std::to_string(playerId) + " has no health component",
260 return;
261 }
262
263 health->current -= damage;
264
265 utl::Logger::log("CollisionSystem: Player " + std::to_string(playerId) + " took " + std::to_string(damage) +
266 " damage (health: " + std::to_string(health->current) + "/" + std::to_string(health->max) +
267 ")",
269
270 // Check if player is dead
271 if (health->current <= 0.0f)
272 {
273 health->current = 0.0f;
274 utl::Logger::log("CollisionSystem: Player " + std::to_string(playerId) + " died", utl::LogLevel::INFO);
276 }
277 }
278
279} // namespace gme
Server-side collision detection and resolution system for R-Type.
This file contains the Logger class.
Class for managing entities and their components.
Definition Registry.hpp:25
T * getComponent(Entity e)
Definition Registry.hpp:71
bool getCollisionInfo(ecs::Entity entity, float &x, float &y, float &radius) const
Extract collision information from an entity.
void update(ecs::Registry &registry, float dt) override
Definition Collision.hpp:29
void handlePlayerPowerupCollision()
Handle collisions between players and powerups.
bool checkCircleCollision(float x1, float y1, float r1, float x2, float y2, float r2, float *overlapDist=nullptr) const
Check for circular collision between two entities.
size_t m_collisionCount
Counter for collisions detected this frame.
void handlePlayerProjectileEnemyCollision()
Handle collisions between player projectiles and enemies.
void applyDamageToEnemy(std::uint32_t enemyId, float damage, std::uint32_t attackerPlayerId=0)
Apply damage to an enemy entity.
ecs::Registry & m_registry
ECS registry reference.
void applyDamageToPlayer(std::uint32_t playerId, float damage)
Apply damage to a player entity.
void handleEnemyProjectilePlayerCollision()
Handle collisions between enemy projectiles and players.
EntityManager & m_entityManager
Entity manager reference for spawning/destruction.
void handlePlayerEnemyCollision()
Handle collisions between players and enemies (ramming)
void addScore(std::uint32_t sessionId, int points)
Add points to a player's score.
void markPlayerAsDead(std::uint32_t sessionId)
Mark a player as dead without destroying the entity.
const std::unordered_map< std::uint32_t, ecs::Entity > & getEnemies() const
Get all enemy entities.
ecs::Entity getPlayerEntity(std::uint32_t sessionId) const
Get player entity by session ID (const version)
EntityMetadata * getEntityMetadata(std::uint32_t networkId)
Get entity metadata by network ID.
const std::unordered_map< std::uint32_t, ecs::Entity > & getPlayers() const
Get all player entities.
void destroyProjectile(std::uint32_t projectileId)
Destroy a projectile entity.
void destroyEnemy(std::uint32_t enemyId)
Destroy an enemy entity.
const std::unordered_map< std::uint32_t, ecs::Entity > & getProjectiles() const
Get all projectile entities.
ecs::Entity getEnemy(std::uint32_t enemyId)
Get enemy entity by network ID.
static void log(const std::string &message, const LogLevel &logLevel)
Definition Logger.hpp:51
std::uint32_t Entity
Definition Entity.hpp:13
constexpr Entity INVALID_ENTITY
Definition Entity.hpp:14
@ ENEMY_ADVANCED
Advanced enemy type (complex behavior)
@ PROJECTILE_PLAYER
Player-fired projectile.
@ ENEMY_BASIC
Basic enemy type (simple behavior)
@ PROJECTILE_ENEMY
Enemy-fired projectile.
@ BOSS
Boss enemy (high health, special patterns)
std::uint32_t ownerId
Owner entity ID (for projectiles, the spawner)