Replaces the procedural brown-rectangle "wolf" with the CraftPix Free Desert Enemy Sprite Sheets hyena. 48×48, side-view, 2-direction via horizontal flip. AnimatedSprite2D mounted in Wolf.setup() and Wolf.from_dict() (same pattern as pawn reskin Slice 1). Anims: idle (4f @ 5fps) + walk (6f @ 10fps). Attack/hurt/death anims skipped for MVP scope. Player-facing copy renamed wolf→hyena in strings.gd (6 entries) and event_catalog.gd (3 EventDef title/body fields). Internal identifiers (class Wolf, World.wolves, EventBus.wolf_spawned, save class_id &"wolf", event IDs like &"lone_wolf") stay the same for save compat — see header comment in wolf.gd. MCP runtime verified: hyena AnimatedSprite2D mounted on spawn, idle anim plays, storyteller modal renders "Lone Hyena — A starving hyena circles your livestock." Sprites: CraftPix Free Desert Enemy Sprite Sheets. License: CraftPix Free (commercial OK, attribution appreciated). https://free-game-assets.itch.io/free-enemy-sprite-sheets-pixel-art Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
34 lines
1.3 KiB
GDScript
34 lines
1.3 KiB
GDScript
class_name HyenaSpriteFrames extends RefCounted
|
||
## Builds a SpriteFrames resource for the Hyena (player-facing "hyena") entity.
|
||
##
|
||
## Atlas layout (single horizontal strip, 48×48 cells):
|
||
## Hyena_idle.png — 192×48 = 4 frames
|
||
## Hyena_walk.png — 288×48 = 6 frames
|
||
##
|
||
## Sprites: CraftPix Free Desert Enemy Sprite Sheets.
|
||
## License: CraftPix Free (commercial OK, attribution appreciated).
|
||
## https://free-game-assets.itch.io/free-enemy-sprite-sheets-pixel-art
|
||
|
||
const FRAME_SIZE: int = 48
|
||
|
||
## Build and return a SpriteFrames with "idle" (4f, 5 fps) and "walk" (6f, 10 fps).
|
||
static func build() -> SpriteFrames:
|
||
var sf := SpriteFrames.new()
|
||
var idle_tex: Texture2D = preload("res://art/sprites/Hyena_idle.png")
|
||
var walk_tex: Texture2D = preload("res://art/sprites/Hyena_walk.png")
|
||
if sf.has_animation(&"default"):
|
||
sf.remove_animation(&"default")
|
||
_add_anim(sf, &"idle", idle_tex, 4, 5.0)
|
||
_add_anim(sf, &"walk", walk_tex, 6, 10.0)
|
||
return sf
|
||
|
||
|
||
static func _add_anim(sf: SpriteFrames, anim_name: StringName, tex: Texture2D, count: int, fps: float) -> void:
|
||
sf.add_animation(anim_name)
|
||
sf.set_animation_loop(anim_name, true)
|
||
sf.set_animation_speed(anim_name, fps)
|
||
for i in count:
|
||
var at := AtlasTexture.new()
|
||
at.atlas = tex
|
||
at.region = Rect2(i * FRAME_SIZE, 0, FRAME_SIZE, FRAME_SIZE)
|
||
sf.add_frame(anim_name, at)
|