Skip to content

Skeleton Warrior

ZarifHilman edited this page Oct 21, 2026 · 4 revisions

← Back to Enemies

Description

Skeleton Warrior is the basic melee enemy in Odysseus and one of the most common enemy types encountered in the game.

It performs melee attacks against the player and can also be summoned by the Necromancer.

The original enemy description also identifies Calypso as a summoner of Skeleton Warriors, although this behaviour has not yet been verified in the examined implementation.

Enemy Stat

Stat Values
HP 30
Damage 2
Attack Type Melee
Speed 3

Components

EnemyFactory.java

EnemyFactory.java is responsible for creating and configuring enemies.

The Skeleton Warrior is created using the createSkeletonWarrior() method.

public static Entity createSkeletonWarrior(Entity target) {
  EnemyConfig config = configs.skeletonWarrior;
  Entity skeletonWarrior = createEnemy(target, config);

The method retrieves the Skeleton Warrior's configuration from EnemyConfigs and uses createEnemy() to create the base enemy entity.

It then configures the Skeleton Warrior's animations, scaling, collision properties, and melee attack.

EnemyAnimationController.java

The Skeleton Warrior uses EnemyAnimationController to manage its animation behaviour.

skeletonWarrior.addComponent(new EnemyAnimationController(target));

This component is attached during enemy creation.

AnimationRenderComponent.java

AnimationRenderComponent is responsible for rendering the Skeleton Warrior's animations.

The animations are loaded from:

images/enemies/skeleton_warrior.atlas

TextureAtlas atlas =
    ServiceLocator.getResourceService()
        .getAsset("images/enemies/skeleton_warrior.atlas", TextureAtlas.class);

AnimationRenderComponent animator =
    new AnimationRenderComponent(atlas);

Three animations are registered:

Animation Description Play Mode
walk Walking animation LOOP
idle Idle animation LOOP
attack Sword attack animation NORMAL
animator.addAnimation(
    "walk",
    WARRIOR_FRAME_TIME,
    Animation.PlayMode.LOOP,
    WARRIOR_ANCHOR_X,
    WARRIOR_ANCHOR_Y);

animator.addAnimation(
    "idle",
    WARRIOR_FRAME_TIME,
    Animation.PlayMode.LOOP,
    WARRIOR_ANCHOR_X,
    WARRIOR_ANCHOR_Y);

animator.addAnimation(
    "attack",
    WARRIOR_ATTACK_DELAY / (WARRIOR_STRIKE_FRAME + 0.5f),
    Animation.PlayMode.NORMAL,
    WARRIOR_ANCHOR_X,
    WARRIOR_ANCHOR_Y);

The attack animation uses a calculated frame time based on the attack delay and strike frame.

HitboxComponent.java

The Skeleton Warrior's hitbox is adjusted to match its character dimensions.

skeletonWarrior
    .getComponent(HitboxComponent.class)
    .setAsBoxAligned(
        new Vector2(bodyWidth, charHeight * 0.9f),
        PhysicsComponent.AlignX.CENTER,
        PhysicsComponent.AlignY.BOTTOM);

The hitbox is aligned horizontally to the centre and vertically to the bottom of the enemy.

SweepAttackTask.java

The Skeleton Warrior uses SweepAttackTask to perform its melee sword attack.

The task is added to the Skeleton Warrior's AITaskComponent during enemy creation.

float attackFrameTime =
    WARRIOR_ATTACK_DELAY / (WARRIOR_STRIKE_FRAME + 0.5f);

float swordReach = WARRIOR_SWORD_REACH_PX * pxToWorld;

skeletonWarrior
    .getComponent(AITaskComponent.class)
    .addTask(
        new SweepAttackTask(
            target,
            20,
            swordReach,
            charHeight,
            WARRIOR_ATTACK_DELAY,
            WARRIOR_ATTACK_FRAMES * attackFrameTime,
            WARRIOR_ATTACK_COOLDOWN));

The task receives the following configuration:

Parameter Description
target Entity being attacked
20 AI task priority
swordReach Attack reach calculated from the sword's pixel dimensions
charHeight Attack height based on the Skeleton Warrior's size
WARRIOR_ATTACK_DELAY Attack wind-up duration
WARRIOR_ATTACK_FRAMES * attackFrameTime Calculated attack duration
WARRIOR_ATTACK_COOLDOWN Cooldown between attacks

The exact attack execution and hit detection will be documented after reviewing SweepAttackTask.java.

Scaling and Collision

The Skeleton Warrior's size is calculated relative to the player's height.

animator.scaleEntity();

float charHeight =
    target.getScale().y * WARRIOR_HEIGHT_VS_PLAYER;

float pxToWorld =
    charHeight / WARRIOR_BODY_HEIGHT_PX;

skeletonWarrior.setScale(
    WARRIOR_FRAME_WIDTH_PX * pxToWorld,
    WARRIOR_FRAME_HEIGHT_PX * pxToWorld);

The calculation converts the character's sprite dimensions into world units.

The physics collider is then adjusted:

float bodyWidth = charHeight * 0.5f;
Vector2 scale = skeletonWarrior.getScale();

PhysicsUtils.setScaledCollider(
    skeletonWarrior,
    bodyWidth / scale.x,
    0.4f * charHeight / scale.y);

This allows the collider to be scaled relative to the Skeleton Warrior's visual dimensions.

Combat Behaviour

Melee Sword Attack

The Skeleton Warrior uses a melee sweep attack against the player.

The attack is configured through SweepAttackTask, which receives the target, attack range, attack height, wind-up duration, total duration, and cooldown.

Its attack priority is set to 20.

The detailed behaviour of the sweep attack will be documented after inspecting the task implementation.

Necromancer Summoning

Skeleton Warriors can also be created by the Necromancer using SummonTask.java.

Entity skeletonWarrior =
    EnemyFactory.createSkeletonWarrior(target);

skeletonWarrior.setPosition(spawnX, spawnY);

necromancer.getEvents().trigger(
    "spawnEntity", skeletonWarrior);

The Necromancer checks eight possible spawn positions and selects the first position not occupied by a nearby enemy.

If no valid position is found, the summon is skipped.

For more details, see the Necromancer Wiki.

Sprite

skeleton_warrior

Testing

The Skeleton Warrior's dedicated test coverage has not yet been verified.

Its creation through EnemyFactory.createSkeletonWarrior() is also exercised by the Necromancer summoning tests in SummonTaskTest.java.

These tests check that summoned Skeleton Warriors are created at expected positions and that consecutive summons do not overlap.

For more information, see the Necromancer Wiki.

Related Documentation

Clone this wiki locally