Combat System
Relevant source files
The following files were used as context for generating this wiki page:The combat system in Souless is a real-time, action-oriented system built for 2D platformer gameplay. It governs all attack and skill interactions between the player character and enemies. The system is highly data-driven, with combat behaviors, animations, and hitboxes defined in configuration files. This allows for a wide variety of skills and attack patterns without changing the core engine logic.
Key components include separate skill systems for players (SkillSystem) and enemies (EnemySkillSystem), a flexible hitbox activation mechanism (SkillHitbox), and a central GameScene that orchestrates collision detection and damage application. Skills can be simple single-hit attacks, complex multi-stage sequences, movement abilities, or status-affecting buffs, all defined through a shared configuration structure.
Core Architecture
The combat architecture is composed of several interconnected classes that manage character actions, skill execution, and collision detection. The GameScene acts as the central hub, while specialized systems handle the logic for players and enemies.
The diagram below illustrates the main classes involved in the combat system and their relationships.
- GameScene: The main orchestrator. In its
updateloop, it facilitates collision checks between player and enemy hitboxes. - Character / EnemyBase: The core entities for the player and enemies. They contain their respective skill systems, state machines, and the
takeDamagemethod. - SkillSystem: Manages the player's skills. It handles skill initialization from configuration, input validation (cooldowns, mana), and execution.
- EnemySkillSystem: Manages enemy skills. It includes AI-driven logic to select and use skills based on range, cooldowns, and target proximity.
- AttackSystem: A simpler system dedicated to handling the player's basic attack, separate from the main
SkillSystem. - SkillHitbox: A crucial class that represents the damage-dealing area of a skill. It can be activated for a set duration or as part of a complex, timed sequence.
Skill & Attack Configuration
All combat abilities for both players and enemies are defined in data objects within characterData.js and enemiesData.js. This data-driven approach allows for easy creation and balancing of skills. Each skill is an object with properties defining its behavior, visuals, and damage.
The most important configuration property is hitboxSequence, an array that defines one or more timed hitbox activations. This allows for complex, multi-hit combos with varying properties for each hit.
Sources: src/config/characterData.js, src/config/enemiesData.js
Key Skill Properties
| Property | Type | Description |
|---|---|---|
type | string | The skill's category (e.g., melee, instant, movement, channeling). This determines which handler processes the skill. |
animation | string | The animation key to play when the skill is used. |
hitboxSequence | array | An array of objects, each defining a step in the attack with its own delay, hitbox properties, damage, and optional movement. |
damage | number | The base damage value for a skill or a specific hitbox step. |
knockback | object | An object with x and y values for the force applied to the target on hit. |
cooldown | number | The time in milliseconds before the skill can be used again. |
hitstop | string | A preset key for a "hit-stop" effect, which briefly freezes the game for impact emphasis. |
impactEffect | string / array | The key for a visual effect to be played at the point of impact. |
movement | object | Defines character movement during a skill, such as a dash. Used in movement type skills or within a hitboxSequence step. |
Sources: src/config/characterData.js:25-44, src/config/enemiesData.js:203-228
Example: Multi-Stage Skill
The fireknight's w_skill is a good example of a hitboxSequence with multiple timed steps.
// src/config/characterData.js:690-721
w_skill: {
type: 'instant',
damage: 25,
icon: 'assets/skills/fireknight/w_skill.png',
hitboxSequence: [
{
delay: 100,
hitbox: {
width: 120,
height: 40,
offsetX: -30,
offsetY: 120,
effect: '',
duration: 200,
},
damage: 10,
},
{
delay: 300,
hitbox: { width: 40, height: 155, offsetX: 40, offsetY: 60, effect: '', duration: 200 },
damage: 10,
},
{
delay: 500,
hitbox: {
width: 150,
height: 130,
offsetX: 130,
offsetY: 60,
effect: '',
duration: 300,
},
damage: 15,
},
],
hitstop: 'FIREKNIGHT',
animation: 'w_skill',
knockback: { x: 200, y: -100 },
effects: ['stun'],
cooldown: 0,
cost: { mana: 0 },
targetType: 'multi',
impactEffect: ['fire_knight_w_skill'], // 타격 시 이펙트
},
This configuration defines a three-hit attack. The first hitbox appears after 100ms, the second after 300ms, and the third after 500ms, each with different dimensions and damage values.
Sources: src/config/characterData.js:690-721
Combat Execution Flow
When a character uses a skill, a series of events is triggered, flowing from input to damage application. The SkillSystem (for players) or EnemySkillSystem (for enemies) orchestrates this process.
The following sequence diagram shows a typical player attack flow.
This diagram shows the process from skill initiation to an enemy taking damage, highlighting the roles of SkillSystem, SkillHitbox, and GameScene.
Sources: src/models/skill_refactoring/SkillSystem.js:199-220, src/entities/enemies/base/EnemyBase.js:372-421, src/scenes/GameScene.js:1010-1013
Hitbox and Damage System
The effectiveness of combat relies on the hitbox system for detecting hits and the takeDamage logic for applying consequences.
Hitbox Activation
The SkillHitbox class is responsible for managing the active damage area of a skill. It is initialized with configuration data that defines its size, offset, and duration.
- Single Hitbox: For simple skills, a single hitbox is activated for a specified duration.
- Sequence Hitbox: For complex skills, the
activateSequencemethod is used. It iterates through thehitboxSequencearray from the skill config and creates temporary hitboxes based on thedelayanddurationof each step. This allows for dynamic, multi-part attacks.
The flow for activating a hitbox sequence is as follows:
Damage Application
When a collision between an active hitbox and a target is detected, the target's takeDamage method is called. This method is defined in EnemyBase.js for all enemies.
The takeDamage method performs the following actions:
- Checks for invincibility or if the target is already dead.
- Enforces a
damageCooldownto prevent the target from being hit too rapidly. - Reduces the target's
hpby the damage amount. - Updates the target's HP bar.
- If HP is depleted, it triggers the death sequence (
playDeath). - If HP remains, it triggers the hit reaction animation (
playHit).
// src/entities/enemies/base/EnemyBase.js:372-421
takeDamage(amount = 1) {
if (this.isDead) return false;
if (this.isInvincible) return false;
const currentTime = this.scene.time.now;
if (currentTime - this.lastDamageTime < this.damageCooldown) {
return false;
}
this.lastDamageTime = currentTime;
this.hp -= amount;
// ... HP bar update logic ...
if (this.hp <= 0) {
// ... phase change logic for bosses ...
// Final death
this.isDead = true;
if (this.sprite.body) this.sprite.body.setVelocity(0);
// ... HP bar visibility logic ...
this.playDeath();
return true; // 죽음
} else {
this.playHit();
return false;
}
}
Sources: src/entities/enemies/base/EnemyBase.js:372-421
Enemy Combat AI
The EnemySkillSystem provides enemies with the ability to use their configured skills intelligently. The associated BossController or EnemyController determines when and what to attack.
The getUsableSkills method is central to this AI. It filters the enemy's available skills based on several criteria:
- Is the skill off cooldown?
- Is the target within the skill's effective
range? - Does the enemy's current HP meet the skill's
hpThreshold(if any)?
This decision-making process is visualized below.
This flow ensures that enemies use their abilities strategically based on the combat situation.
Sources: src/entities/enemies/systems/EnemySkillSystem.js:147-174, src/entities/enemies/base/EnemyBase.js:132-154
After selecting a skill, the EnemySkillSystem handles execution, including turning to face the target, playing animations, and activating the corresponding hitboxes.
Sources: src/entities/enemies/systems/EnemySkillSystem.js:186-200
Conclusion
The combat system in Souless is a robust and extensible framework that separates logic from data. By defining skills, animations, and hitboxes in configuration files, developers can easily create diverse and engaging combat encounters for both player characters and enemies. The system's core strengths lie in its flexible hitboxSequence mechanism for creating complex attacks and the clear separation of responsibilities between skill management, collision detection, and AI decision-making.