9#include "../../Components/Enemy.hpp"
10#include "../../Components/IComponent.hpp"
11#include "../../Components/OrbitalModule.hpp"
12#include "../../Components/Projectile.hpp"
13#include "../../Components/Wall.hpp"
22 std::vector<std::uint32_t> entitiesVec(entities.begin(), entities.end());
23 std::vector<std::uint32_t> projectilesToDestroy;
26 std::vector<Address> entitiesToDestroy;
28 for (
size_t i = 0; i < entitiesVec.size(); ++i) {
29 for (
size_t j = i + 1; j < entitiesVec.size(); ++j) {
30 auto entity1 = entitiesVec[i];
31 auto entity2 = entitiesVec[j];
46 if (!
canCollide(collider1.getLayer(), collider1.getMask(), collider2.getLayer(),
47 collider2.getMask())) {
51 if (
checkAABB(transform1.getPosition(), collider1.getSize(), collider1.getOffset(),
52 transform2.getPosition(), collider2.getSize(), collider2.getOffset())) {
68 if (entity1IsPlayer && entity2IsWall) {
71 }
else if (entity2IsPlayer && entity1IsWall) {
77 if (entity1IsOrbitalModule && entity2IsEnemy) {
79 }
else if (entity2IsOrbitalModule && entity1IsEnemy) {
84 if (entity1IsOrbitalModule && entity2IsProjectile) {
86 }
else if (entity2IsOrbitalModule && entity1IsProjectile) {
91 if ((entity1IsPlayer && entity2IsCollectible) ||
92 (entity2IsPlayer && entity1IsCollectible)) {
93 LOG_DEBUG(
"[COLLISION] Player-Collectible collision detected: E", entity1,
" & E",
97 if (entity1IsPlayer && entity2IsCollectible) {
98 handlePickup(entity1, entity2, registry, entitiesToDestroy);
99 }
else if (entity2IsPlayer && entity1IsCollectible) {
100 handlePickup(entity2, entity1, registry, entitiesToDestroy);
110 for (
Address addr : entitiesToDestroy) {
118 std::vector<Address> &entitiesToDestroy) {
131 LOG_INFO(
"[PICKUP] Player ", playerAddr,
" collected item at entity ", collectibleAddr);
144 const char *buffName =
"Unknown";
147 buffName =
"SpeedBoost";
150 buffName =
"DamageBoost";
153 buffName =
"FireRateBoost";
159 buffName =
"HealthRegen";
162 buffName =
"MultiShot";
165 buffName =
"DoubleShot";
168 buffName =
"TripleShot";
171 buffName =
"PiercingShot";
174 buffName =
"HomingShot";
177 buffName =
"MaxHealthIncrease";
181 if (duration > 0.0f) {
182 LOG_INFO(
" ✓ Applied buff: ", buffName,
" (duration: ", duration,
183 "s, value: ", collectible.
getValue(),
")");
185 LOG_INFO(
" ✓ Applied PERMANENT upgrade: ", buffName,
" (value: ", collectible.
getValue(),
193 int increase =
static_cast<int>(collectible.
getValue());
222 entitiesToDestroy.push_back(collectibleAddr);
223 }
catch (
const std::exception &e) {
237 const OrbitalModule &
module = registry.getComponent<OrbitalModule>(moduleAddr);
238 int damage =
module.getDamage();
246 LOG_DEBUG(
"[COLLISION] Orbital module E", moduleAddr,
" hit enemy E", enemyAddr,
" for ", damage,
255 std::vector<Address> &entitiesToDestroy) {
265 LOG_DEBUG(
"[COLLISION] Orbital module E", moduleAddr,
" blocked enemy projectile E",
269 entitiesToDestroy.push_back(projectileAddr);
281 float left1 = pos1.
x + offset1.
x - (size1.
x / 2.0f);
282 float right1 = left1 + size1.
x;
283 float top1 = pos1.
y + offset1.
y - (size1.
y / 2.0f);
284 float bottom1 = top1 + size1.
y;
286 float left2 = pos2.
x + offset2.
x - (size2.
x / 2.0f);
287 float right2 = left2 + size2.
x;
288 float top2 = pos2.
y + offset2.
y - (size2.
y / 2.0f);
289 float bottom2 = top2 + size2.
y;
291 return !(right1 < left2 || left1 > right2 || bottom1 < top2 || top1 > bottom2);
302 (void)playerTransform;
303 (void)playerCollider;
308 LOG_INFO(
"[COLLISION] Player touched wall - instant death!");
321 std::uint32_t mask2)
const {
322 return (mask1 & layer2) && (mask2 & layer1);
336 std::uint32_t entity2,
337 std::vector<Address> &entitiesToDestroy) {
343 if (!entity1IsProjectile && !entity2IsProjectile) {
348 std::uint32_t projectileAddr = entity1IsProjectile ? entity1 : entity2;
349 std::uint32_t targetAddr = entity1IsProjectile ? entity2 : entity1;
352 for (
Address addr : entitiesToDestroy) {
353 if (addr == projectileAddr) {
375 if (projectile.
isFriendly() && !targetIsEnemy) {
380 if (!projectile.
isFriendly() && !targetIsPlayer) {
386 int damage =
static_cast<int>(projectile.
getDamage());
388 bool damageApplied = targetHealth.
takeDamage(damage);
393 LOG_INFO(
"[PROJECTILE HIT] Player projectile (E", projectileAddr,
") hit enemy (E",
394 targetAddr,
") for ", damage,
" damage. HP: ", targetHealth.
getCurrentHealth(),
"/",
396 }
else if (targetIsPlayer) {
397 LOG_INFO(
"[PROJECTILE HIT] Enemy projectile (E", projectileAddr,
") hit player (E",
398 targetAddr,
") for ", damage,
" damage. HP: ", targetHealth.
getCurrentHealth(),
"/",
404 entitiesToDestroy.push_back(projectileAddr);
409 return (1ULL << getComponentType<Transform>()) | (1ULL << getComponentType<Collider>());
Component managing active buffs on an entity.
void addBuff(BuffType type, float duration, float value)
Add a new buff.
Component for items that can be picked up by players.
bool grantsBuff() const
Check if this grants a buff.
bool awardsScore() const
Check if this awards score.
bool restoresHealth() const
Check if this restores health.
float getDuration() const
Get buff duration.
BuffType getBuffType() const
Get buff type (if applicable)
int getHealthRestore() const
Get health restore amount.
float getValue() const
Get buff value.
int getScoreValue() const
Get score value.
Component for collision detection and physics interactions.
void resolveWallCollision(Address playerAddr, Address wallAddr, Transform &playerTransform, Collider &playerCollider, Transform &wallTransform, Collider &wallCollider, Registry ®istry)
Resolves collision between player and wall by instantly killing the player.
ComponentMask getComponentMask() const override
Gets the component mask for this system.
void handleProjectileCollision(Registry ®istry, std::uint32_t entity1, std::uint32_t entity2, std::vector< Address > &entitiesToDestroy)
Handle projectile collision with other entities.
void handleModuleProjectileCollision(Address moduleAddr, Address projectileAddr, Registry ®istry, std::vector< Address > &entitiesToDestroy)
Handle collision between orbital module and projectile.
void handlePickup(Address playerAddr, Address collectibleAddr, Registry ®istry, std::vector< Address > &entitiesToDestroy)
Handle collision between player and collectible.
void handleModuleEnemyCollision(Address moduleAddr, Address enemyAddr, Registry ®istry)
Handle collision between orbital module and enemy.
bool canCollide(std::uint32_t layer1, std::uint32_t mask1, std::uint32_t layer2, std::uint32_t mask2) const
Checks if two entities can collide based on layers.
void update(Registry ®istry, float deltaTime) override
Detects and handles collisions between entities.
bool checkAABB(const Transform::Vector2 &pos1, const Collider::Vector2 &size1, const Collider::Vector2 &offset1, const Transform::Vector2 &pos2, const Collider::Vector2 &size2, const Collider::Vector2 &offset2) const
Checks AABB collision between two entities.
Component identifying an entity as an enemy with AI behavior.
Component representing entity health and invincibility.
bool takeDamage(int amount)
Apply damage to the entity. Respects invincibility frames - no damage taken if invincible.
int getCurrentHealth() const
Get current health points.
void setCurrentHealth(int health)
Set current health.
int getMaxHealth() const
Get maximum health points.
void setMaxHealth(int health)
Set maximum health.
Component for entities that orbit around a parent entity (like drones in Isaac).
Component identifying an entity as a player with game statistics.
void setScore(int score)
Set player's score.
int getScore() const
Get player's score.
Component for projectile entities (bullets, missiles, etc.).
bool isFriendly() const
Check if projectile is friendly.
float getDamage() const
Get damage value.
Manages entities, their signatures and component type registrations.
void destroyEntity(Address address)
Remove an entity and its Signature from the registry.
std::vector< Address > getEntitiesWithMask(Signature requiredMask)
Get all entities matching a specific component mask.
T & getComponent(Address address)
Get a component from an entity.
bool hasComponent(Address address)
Check if an entity has a specific component.
void setComponent(Address address, const T &component)
Set/add a component to an entity with its data.
Component for static or destructible walls/obstacles.
Maximum number of distinct component types supported by the Registry.
@ PiercingShot
Projectiles pierce through enemies.
@ TripleShot
Fire three projectiles at once.
@ DamageBoost
Increases weapon damage.
@ HomingShot
Projectiles home towards enemies.
@ FireRateBoost
Increases fire rate.
@ MaxHealthIncrease
Permanently increase max health.
@ Shield
Temporary invincibility.
@ HealthRegen
Regenerates health over time.
@ SpeedBoost
Increases movement speed.
@ MultiShot
Shoot in multiple directions.
@ DoubleShot
Fire two projectiles at once.
std::uint32_t Address
Type used to represent an entity address/ID.
std::uint64_t ComponentMask
Type alias for component bitmask.
2D vector for size and offset.