rimlike/scenes/pawn/pawn_sprite_frames.gd
megaproxy b4c9541eae Pawn reskin Slice 1 — peasant sprites replace coloured disc
Pawns now render as AnimatedSprite2D children sourced from ElvGames
"Farming Characters Pack" atlases (Pack 1, characters 001-015). Each
pawn picks one of 15 peasants deterministically from name hash:
Bram=004, Cora=013, Edda=001.

Animations: idle_down/left/right/up + walk_down/left/right/up (4 fps
idle, 8 fps walk, looped) + dead (single frame, no loop). Pawn picks
animation each _process tick from (is_downed, is_walking, facing).
Facing is now a Vector2i field updated in _advance_walk; round-trips
through save/load.

Sprite mounting is deferred from _ready() to setup() / from_dict()
because the atlas pick depends on pawn_name, which isn't assigned at
_ready time.  _mount_sprite() is idempotent for the save-load chain.

_atlas_for_pawn(pawn) is the single Slice-2 extension point —
swapping atlases based on equipped armor in a future sprint is a
one-function change.

_draw() stripped of body disc + downed-rotation; now overlay-only
(selection ring + carry indicator). AnimatedSprite2D child uses
z_index=-1 so the overlays stay on top.

45 PNGs copied into art/sprites/characters/ + 45 .import companions.
2026-05-16 15:23:18 +01:00

51 lines
2.1 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class_name PawnSpriteFrames extends RefCounted
## Builds a SpriteFrames resource from a {idle, walk, dead} atlas trio for a
## peasant character. Atlases are 128×128 with 4 rows (down/left/right/up)
## × 4 frames (32×32 cells). Idle + Walk produce 4 directional animations
## each (loop=true); Dead is a single frame (loop=false) from row 0.
##
## Created via PawnSpriteFrames.build(atlases) from Pawn._ready(). The
## returned SpriteFrames is assigned to an AnimatedSprite2D's sprite_frames.
const CELL: int = 32
const DIRS: Array[StringName] = [&"down", &"left", &"right", &"up"]
## Build a SpriteFrames containing:
## idle_down/left/right/up — 4 frames each, loop, 4 fps
## walk_down/left/right/up — 4 frames each, loop, 8 fps
## dead — 1 frame, no loop (from idle/dead row 0 col 0)
##
## `atlases` is a Dictionary with three Texture2D values keyed by "idle",
## "walk", "dead". Each texture is 128×128.
static func build(atlases: Dictionary) -> SpriteFrames:
var sf := SpriteFrames.new()
# AnimatedSprite2D auto-creates a `default` animation; remove it so the
# scene doesn't render an empty placeholder if a caller mistypes an anim name.
if sf.has_animation(&"default"):
sf.remove_animation(&"default")
_add_directional(sf, &"idle", atlases["idle"], true, 4.0)
_add_directional(sf, &"walk", atlases["walk"], true, 8.0)
# Dead — single 32×32 frame from row 0 (down-facing) of the dead atlas.
sf.add_animation(&"dead")
sf.set_animation_loop(&"dead", false)
var dead_at := AtlasTexture.new()
dead_at.atlas = atlases["dead"]
dead_at.region = Rect2(0, 0, CELL, CELL)
sf.add_frame(&"dead", dead_at)
return sf
static func _add_directional(sf: SpriteFrames, prefix: StringName, tex: Texture2D, loop: bool, fps: float) -> void:
for row in 4:
var anim_name := StringName("%s_%s" % [prefix, DIRS[row]])
sf.add_animation(anim_name)
sf.set_animation_loop(anim_name, loop)
sf.set_animation_speed(anim_name, fps)
for col in 4:
var at := AtlasTexture.new()
at.atlas = tex
at.region = Rect2(col * CELL, row * CELL, CELL, CELL)
sf.add_frame(anim_name, at)