Repository navigation
Skeleton Warrior
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.
| Stat | Values |
|---|---|
| HP | 30 |
| Damage | 2 |
| Attack Type | Melee |
| Speed | 3 |
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.
The Skeleton Warrior uses EnemyAnimationController to manage its animation behaviour.
skeletonWarrior.addComponent(new EnemyAnimationController(target));This component is attached during enemy creation.
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.
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.
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.
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.
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.
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.
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.
Entities and Components
Input Handling
Arrow Selection Wheel Arrow Selection Wheel — Sprint 3
Game Screens and Areas
Enemies
-
Individual Enemy Pages:
-
Misc Enemy Pages: