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.
This commit is contained in:
parent
da55bf312c
commit
b4c9541eae
94 changed files with 1960 additions and 19 deletions
51
scenes/pawn/pawn_sprite_frames.gd
Normal file
51
scenes/pawn/pawn_sprite_frames.gd
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue