Files
Takeshi b84bade045 Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
2026-10-11 15:58:00 +09:00

92 lines
4.2 KiB
GDScript

class_name PixelPeople
extends RefCounted
## Authored side-view poses on a 16x18 grid. No neighbouring atlas characters
## are used as animation frames. All motion is presentation-only.
const COATS := [Color("688da0"), Color("b87659"), Color("a69a63"), Color("89789e"), Color("638d72")]
const SKINS := [Color("edc49d"), Color("c99371"), Color("a56f50")]
const INK := Color("303c40")
static func pose(mode: StringName, frame: int, variant: int, staff: bool) -> Array[Dictionary]:
var marks: Array[Dictionary] = []
var skin: Color = SKINS[posmod(variant, SKINS.size())]
var coat: Color = Color("719d94") if staff else COATS[posmod(variant, COATS.size())]
var phase := posmod(frame, 8)
var walk := mode == &"walk" or mode == &"carry_walk"
var work := mode in [&"work", &"clean", &"eat"]
var stride := [0, 1, 2, 1, 0, -1, -2, -1][phase] as int
var bob := -1 if walk and phase in [2, 6] else 0
if mode == &"standard_room_sleep":
# General-room presentation only: same16x18 actor grid and original skin.
# Breathing follows existing visual frame; no Clock, guest or service change.
var breathing := -1 if phase in [2, 3, 4] else 0
mark(marks, Rect2(2, 14, 13, 2), INK)
mark(marks, Rect2(2, 11, 5, 4), Color("eee5c9"))
mark(marks, Rect2(3, 12, 4, 3), skin)
mark(marks, Rect2(2, 12, 2, 3), INK)
mark(marks, Rect2(5, 13, 2, 1), INK)
mark(marks, Rect2(7, 11 + breathing, 8, 5 - breathing), INK)
mark(marks, Rect2(8, 12 + breathing, 6, 3 - breathing), Color("608d84"))
mark(marks, Rect2(8, 12 + breathing, 6, 1), Color("eee5c9"))
mark(marks, Rect2(9, 14 + breathing, 4, 1), Color("719d94"))
mark(marks, Rect2(6, 13 + breathing, 2, 1), skin)
mark(marks, Rect2(14, 14, 1, 2), INK)
return marks
if mode in [&"sleep", &"collapsed"]:
mark(marks, Rect2(2, 14, 12, 2), INK)
mark(marks, Rect2(3, 12, 4, 3), skin)
mark(marks, Rect2(2, 12, 2, 3), INK)
mark(marks, Rect2(7, 12, 6, 3), coat)
mark(marks, Rect2(13, 13, 2, 2), INK)
if mode == &"sleep":
mark(marks, Rect2(3 + phase / 3, 8 - phase / 3, 2, 1), Color("eee6c7"))
return marks
# Far arm and leg, then silhouette, face, near arm and leg.
mark(marks, Rect2(6, 8 + bob, 2, 5), coat.darkened(0.25))
var far := -stride if walk else 0
var near := stride if walk else 0
mark(marks, Rect2(7 + far, 12 + bob, 2, 4 - bob), INK.lightened(0.12))
mark(marks, Rect2(7 + far, 16, 3, 1), INK)
mark(marks, Rect2(6, 6 + bob, 5, 7), INK)
mark(marks, Rect2(7, 7 + bob, 4, 5), coat)
mark(marks, Rect2(7, 1 + bob, 4, 5), skin)
mark(marks, Rect2(6, 1 + bob, 4, 2), INK)
mark(marks, Rect2(6, 3 + bob, 1, 2), INK)
mark(marks, Rect2(11, 3 + bob, 1, 2), skin)
mark(marks, Rect2(10, 3 + bob, 1, 1), INK)
mark(marks, Rect2(8, 6 + bob, 2, 1), skin)
mark(marks, Rect2(8 + near, 12 + bob, 2, 4 - bob), INK)
mark(marks, Rect2(8 + near, 16, 3, 1), INK)
var arm := -stride if walk else 0
if work:
arm = 2 if phase < 4 else 1
mark(marks, Rect2(9 + arm, 8 + bob, 2, 3), coat.lightened(0.12))
mark(marks, Rect2(9 + arm, 11 + bob, 2, 1), skin)
if staff:
mark(marks, Rect2(7, 9 + bob, 2, 3), Color("e3dfc2"))
if mode in [&"carry", &"carry_walk"]:
mark(marks, Rect2(10, 8 + bob, 5, 5), Color("956940"))
mark(marks, Rect2(10, 8 + bob, 5, 1), Color("d3ad6b"))
mark(marks, Rect2(12, 9 + bob, 1, 4), Color("b48850"))
elif mode == &"clean":
mark(marks, Rect2(11 + arm, 9, 1, 7), Color("af9059"))
mark(marks, Rect2(9 + arm, 16, 5, 1), Color("d8bc78"))
elif mode == &"eat":
mark(marks, Rect2(11, 6 if phase < 4 else 10, 3, 2), Color("f3ebcf"))
elif mode == &"work":
mark(marks, Rect2(11, 12, 4, 1), Color("efe7ce"))
mark(marks, Rect2(12 + phase % 2, 10, 1, 2), Color("805e44"))
elif mode == &"wait":
mark(marks, Rect2(9, 9, 3, 1), skin)
return marks
static func mark(marks: Array[Dictionary], rect: Rect2, color: Color) -> void:
marks.append({&"rect": rect, &"color": color})
static func draw(canvas: CanvasItem, origin: Vector2, pixel: float, mode: StringName, frame: int, variant: int, staff: bool, facing_left: bool) -> void:
for item: Dictionary in pose(mode, frame, variant, staff):
var rect: Rect2 = item[&"rect"]
if facing_left:
rect.position.x = 16 - rect.end.x
canvas.draw_rect(Rect2(origin + rect.position * pixel, rect.size * pixel), item[&"color"])