Enemy AI and Management
Relevant source files
The following files were used as context for generating this wiki page:The Enemy AI and Management system is a core component of the Souless project, responsible for the entire lifecycle of non-player characters (NPCs), from their creation and behavior to their eventual defeat. The system is designed to be data-driven, with enemy properties and AI logic defined in a central configuration file. It supports a distinction between standard enemies with simple patrol/attack patterns and complex bosses with multi-phase battles and sophisticated skill sets.
This document outlines the architecture of the enemy system, detailing how enemies are configured, spawned, and controlled within the game world.
Core Architecture
The enemy system is composed of several key classes that work together to manage enemy entities. The EnemyManager oversees spawning, while EnemyBase provides the foundational properties and methods for all enemies. AI logic is encapsulated in EnemyController and its specialized subclass BossController, which in turn utilize EnemyAttackSystem and EnemySkillSystem to execute attacks.
This diagram illustrates the relationships between the main components of the enemy system.
Enemy Configuration
All enemy properties, from stats and animations to AI behavior, are defined in the EnemiesData object within src/config/enemiesData.js. This centralized, data-driven approach allows for easy creation and modification of enemy types without changing game logic.
Configuration Structure
Each enemy type is a key in the EnemiesData object, containing several configuration blocks.
| Property | Description |
|---|---|
type | The category of the enemy, either normal or boss. This determines which controller is used. |
sprite | Defines visual properties like spritesheet dimensions, scale, and flipping. |
physics | Configures the physics body, including size, offset, and world collision. |
stats | Contains base statistics such as maxHP, speed, expReward, and damageCooldown. |
assets | Maps animation states (e.g., idle, hit) to their corresponding asset paths. |
animations | Defines the frame data for each animation, including start/end frames and frame rate. |
ai | The core of the enemy's behavior, defining its AI type, detection ranges, and attack/skill definitions. |
Sources: src/config/enemiesData.js:1-55
Example: Normal Enemy (slime)
// src/config/enemiesData.js:2-49
slime: {
type: 'normal',
// ... sprite, physics, stats ...
ai: {
type: 'patrol',
detectRange: 180,
attack: {
range: 60,
damage: 1,
cooldown: 1800,
hitDelay: 200,
},
},
},
Example: Boss Enemy (assassin_boss)
Bosses have a more complex ai configuration, including multiple skills, movement ranges, and phase data.
// src/config/enemiesData.js:240-362
assassin_boss: {
type: 'boss',
// ... stats, assets ...
stats: {
maxHP: 500,
speed: { min: 50, max: 50 },
runSpeed: 120,
// ...
},
ai: {
type: 'boss',
detectRange: 1200,
attack: {
attackRange: 80, // Stop and attack distance
walkRange: 1200, // Walking distance
runRange: 250, // Running distance
},
skillNames: ['attack', 'shadowDash'],
skills: {
attack: { /* ... skill config ... */ },
shadowDash: { /* ... skill config ... */ }
}
},
},
Sources: src/config/enemiesData.js:240-362
Enemy Spawning and Management
The EnemyManager class is responsible for populating maps with enemies. It reads configuration from mapData.js to determine which enemy types to spawn, how many, and how often.
Sources: src/controllers/EnemyManager.js
Spawning Process
- Initial Spawn: When a map is loaded,
EnemyManager.createInitial()is called to spawn aninitialCountof enemies. - Continuous Spawning: The
EnemyManager.update()method continuously checks if the number of active enemies is belowmaxCount. - Respawn Logic: If the count is low and the
respawnIntervalhas passed, a new enemy is spawned at a random location, ensuring it is at leastminPlayerDistanceaway from the player. - Enemy Creation: The manager selects a random enemy type from the map's configured list and instantiates the corresponding class (e.g.,
Slime,Bat).
This flowchart shows the enemy respawn logic within the EnemyManager's update loop.
Enemy Lifecycle and State
The EnemyBase class serves as the blueprint for all enemies, managing their state from creation to death.
Sources: src/entities/enemies/base/EnemyBase.js
Key States and Properties
hp: The enemy's current health.isDead: A boolean flag that is set totruewhen HP reaches zero.isBeingHit: A flag that temporarily stops AI actions when the enemy takes damage, playing a "hit" animation.isInvincible: Prevents the enemy from taking damage, used primarily during boss phase transitions.
Damage and Death Flow
The takeDamage method is central to the enemy lifecycle.
- Cooldown Check: It first checks if the
damageCooldownhas passed since the last hit. - HP Reduction: If damage is applied,
hpis reduced. - HP Bar Update: The visual HP bar is updated to reflect the new health percentage.
- Death Check: If
hpis 0 or less, the enemy enters the death sequence.- For bosses with multiple phases, it triggers a phase change instead of death if not on the final phase.
- For normal enemies or bosses on their final phase,
isDeadis set totrue.
- Animation:
playHit()is called on taking damage, orplayDeath()is called upon defeat. - Soul Spawning: After the death animation completes,
spawnSoul()is called, which creates a soul entity for the player to collect before the enemy object is destroyed. - Destruction: The
destroy()method cleans up all associated game objects (sprite, HP bar) and grants experience points to the player.
This diagram shows the basic state transitions for an enemy.
AI and Behavior Controllers
AI behavior is handled by controller classes that are assigned to an enemy based on its type in enemiesData.js.
EnemyController (Normal Enemies)
This controller implements a simple AI for normal type enemies.
- Behavior: The enemy patrols a small area. When the player enters its
detectRange, it gives chase. If the player is withinattackRange, it stops and attacks. - Update Loop: In each frame, it finds the target (player), checks the distance, and decides whether to patrol, chase, or attack.
Sources: src/entities/enemies/base/EnemyBase.js:203-211
BossController (Bosses)
BossController extends EnemyController to manage more complex behaviors for boss type enemies.
Advanced Movement
Bosses have more nuanced movement based on distance to the target:
detectRange: The maximum distance at which a boss will notice the player.walkRangeandrunRange: Defines two zones for different movement speeds, allowing the boss to walk when far and run when closer.attackRange: The distance at which the boss stops moving to initiate an attack.
Sources: src/entities/enemies/systems/BossController.js:12-19
Skill-Based AI
Instead of a single attack, bosses use the EnemySkillSystem to choose from a list of available skills defined in ai.skillNames.
- The
tryAttackOrSkillmethod evaluates all usable skills based on range, cooldown, and priority. - It selects the highest-priority skill that can be used at the current distance.
- This allows for dynamic combat where a boss might use a ranged attack when the player is far and a melee attack when close.
Sources: src/entities/enemies/systems/BossController.js:231-297
Phase System
A key feature of the BossController is the multi-phase battle system.
- Configuration:
maxPhaseandphaseThresholds(HP percentages) are defined inenemiesData.js. - Transition: When a boss's HP drops below a threshold,
checkPhaseTransitiontriggers the transition. The boss becomes invincible, a scene effect may play, and its stats and behavior can change. - Phase Changes: The
applyPhaseChangesmethod modifies the boss's properties for the new phase, such as increasing speed or reducing skill cooldowns.
This sequence diagram shows the process of a boss transitioning to its next phase.
Attack and Skill Systems
The execution of attacks and skills is handled by dedicated systems.
EnemyAttackSystem
This system manages simple, single-hitbox attacks. It is primarily used by normal enemies and is configured directly from the ai.attack object in enemiesData.js. It handles attack cooldowns, animation playback, and triggering a hitbox at the correct time.
Sources: src/entities/enemies/base/EnemyBase.js:167-177
EnemySkillSystem
This is a more powerful system used by bosses to manage a variety of complex skills. It reads the ai.skills object from enemiesData.js.
Key Features
- Skill Registration: It parses the skill configurations and creates
Skillobjects for each one. hitboxSequence: This is a crucial feature that allows a single skill to have multiple, timed hitboxes with different properties (damage, size, duration, effects). This enables complex combo attacks, like thesemi_boss'ssoulBallskill which has a moving projectile part and a final explosion part.- Skill Types: It supports various skill types, including
melee,instant,movement, andaoe. - Movement Integration: Skills of type
movement(e.g., a dash) can be defined with properties likespeedandduration. The system handles the movement logic.
The following diagram shows the flow of executing a skill with a hitboxSequence.
Conclusion
The enemy AI and management system in Souless is a robust and flexible framework. Its data-driven design, centered around enemiesData.js, allows for rapid development and iteration of enemy behaviors. The clear separation of concerns—with EnemyManager for spawning, EnemyBase for state, controllers for AI, and skill systems for execution—creates a modular and extensible architecture. The advanced features within BossController and EnemySkillSystem, such as multi-phase battles and complex hitboxSequence attacks, provide the tools needed to create engaging and challenging boss encounters.