summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/VillageArt.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 13:15:39 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 13:15:39 +0800
commit0b9753543bd726818c61d76384d56a30b862e1ac (patch)
tree06b21006dc540b5d9995caf394bb4c8084b9294e /src/LivingVillage.Desktop/VillageArt.fs
parent76a6850bb88546fc21f5f78a53fbda04e77c8b52 (diff)
downloadliving-village-0b9753543bd726818c61d76384d56a30b862e1ac.tar.gz
feat(desktop): 村民与主角四帧行走动画
人物图集 5 变体 x 4 向 x 4 帧(2560x48,全部经 make-jiangnan-art.py 原创,四种腿步:站立/左跨/站立微跳/右跨镜像);animationFrame 按 tick/4 mod 4 确定性取帧(16 tick 一循环,禁实时时钟);快照式回归断言四帧循环与逐帧图集列映射,主角同规则。
Diffstat (limited to 'src/LivingVillage.Desktop/VillageArt.fs')
-rw-r--r--src/LivingVillage.Desktop/VillageArt.fs15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs
index db25757..6f5af07 100644
--- a/src/LivingVillage.Desktop/VillageArt.fs
+++ b/src/LivingVillage.Desktop/VillageArt.fs
@@ -84,6 +84,8 @@ module VillageArt =
type AnimationFrame =
| FrameOne
| FrameTwo
+ | FrameThree
+ | FrameFour
type NpcSpriteSpec =
{ Variant: NpcVisualVariant
@@ -250,8 +252,13 @@ module VillageArt =
let remainder = value % divisor
if remainder < 0L then remainder + divisor else remainder
+ /// Four-pose walk cycle over a 16-tick window (one pose per 4 sim ticks).
let animationFrame (tick: int64) : AnimationFrame =
- if positiveModulo64 8L tick < 4L then FrameOne else FrameTwo
+ match positiveModulo64 4L (tick / 4L) with
+ | 0L -> FrameOne
+ | 1L -> FrameTwo
+ | 2L -> FrameThree
+ | _ -> FrameFour
/// Water surface ripple phase: flips every 32 simulation ticks, fully deterministic.
let waterFrameTick (tick: int64) : int =
@@ -303,7 +310,9 @@ module VillageArt =
match spec.Frame with
| FrameOne -> 0
| FrameTwo -> 1
- let cellIndex = (variantIndex * 4 + directionIndex) * 2 + frameIndex
+ | FrameThree -> 2
+ | FrameFour -> 3
+ let cellIndex = (variantIndex * 4 + directionIndex) * 4 + frameIndex
Microsoft.Xna.Framework.Rectangle(cellIndex * 32, 0, 32, 48)
let private rgba (r: int) (g: int) (b: int) (a: int) : XnaColor = XnaColor(r, g, b, a)
@@ -320,7 +329,7 @@ module VillageArt =
let worldTileCount = 21
let worldAtlasWidth = Sim.tilePixels * worldTileCount
let worldAtlasHeight = Sim.tilePixels
- let characterAtlasWidth = 32 * 5 * 4 * 2
+ let characterAtlasWidth = 32 * 5 * 4 * 4
let characterAtlasHeight = 48
let interiorAtlasWidth = 392
let interiorAtlasHeight = 96