ShootSystem
The ShootSystem manages weapon firing logic for both Players and AI. It handles the creation of projectile entities, enforces fire rates, and determines shooting direction.
Required Components
Entities processed by this system must have:
1. Weapon: Stores damage, fire rate, and projectile type.
2. Transform: Origin point for the projectile.
3. InputComponent (Optional): If present, marks the entity as a Player (controlled by keys). If absent, treated as AI.
Logic & Algorithm
-
Fire Trigger:
- Player: Checks
InputComponentforGameAction::SHOOT. - AI: Uses a simple temporal pattern (e.g., shoot for 100ms every 2 seconds). TODO: Integrate with AISystem.
- Player: Checks
-
Fire Rate Check:
- Compares
currentTime(ms) withlastShotTime + fireRateMs. - If valid, updates
lastShotTimeand proceeds to spawn.
- Compares
-
Projectile Spawning:
- Direction:
- Player: Always shoots Right
(1.0, 0.0). - Enemy: Always shoots Left
(-1.0, 0.0).
- Player: Always shoots Right
- Asset Selection: Maps
Weapon.projectileTypeto specific visual assets (e.g.,MISSILE->DEFAULT_BULLET). - Component Creation: Spawns a new Entity with:
Velocity: Calculated based on direction * speed (1.5 units/ms).Projectile: Stores ownership (shooterId) and damage.HitBox: Enables collision.
- Direction:
Usage
Attach a Weapon component to any entity to give it shooting capabilities.
// Example: Giving a weapon to a player
gameEngine.addComponent(player, Weapon(
200, // Fire Rate (ms)
0, // Last Shot Time
10, // Damage
ProjectileType::MISSILE
));
Code reference
src/game/src/systems/ShootSystem.cpp
void ShootSystem::onUpdate(float dt) {
uint32_t now = ms_since_epoch();
auto& weapons = _engine.getComponents<Weapon>();
auto& transforms = _engine.getComponents<Transform>();
auto& inputs = _engine.getComponents<InputComponent>();
for (size_t e : _entities) {
if (!weapons[e] || !transforms[e]) continue;
auto& weapon = weapons[e].value();
auto& transform = transforms[e].value();
bool isPlayer = inputs[e].has_value();
bool shouldShoot = isPlayer ? inputs[e]->activeActions[GameAction::SHOOT]
: (now % 2000) < 100;
if (shouldShoot && canShoot(weapon, now)) {
auto [dx, dy] = calculateDirection(Entity::fromId(e));
weapon.lastShotTime = now;
spawnProjectile(Entity::fromId(e), transform.x, transform.y, dx, dy, isPlayer, weapon);
}
}
}