From b237a11908442a227361fae24dbdd0dbb287fac9 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Fri, 18 Sep 2026 22:48:42 +0800 Subject: feat: M0 骨架 — F# 解决方案 + MonoGame DesktopGL 游戏循环 + 32x32 瓦片地图 + 化身 WASD + 镜头跟随 + FPS 计数 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/LivingVillage.Kernel/Sim.fs | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/LivingVillage.Kernel/Sim.fs (limited to 'src/LivingVillage.Kernel/Sim.fs') diff --git a/src/LivingVillage.Kernel/Sim.fs b/src/LivingVillage.Kernel/Sim.fs new file mode 100644 index 0000000..d1b2e57 --- /dev/null +++ b/src/LivingVillage.Kernel/Sim.fs @@ -0,0 +1,46 @@ +namespace LivingVillage.Kernel + +module Sim = + + type Vec2 = + { X: float32 + Y: float32 } + + type Avatar = + { Pos: Vec2 } + + type Input = + { MoveX: float32 + MoveY: float32 } + + type TimeStep = + { Dt: float32 + Input: Input } + + type World = + { Tick: int64 + Avatar: Avatar } + + let mapWidthTiles = 64 + let mapHeightTiles = 48 + let tilePixels = 32 + let avatarSpeed = 160.0f + + let initialWorld () : World = + let centerX = float32 (mapWidthTiles * tilePixels / 2 - tilePixels / 2) + let centerY = float32 (mapHeightTiles * tilePixels / 2 - tilePixels / 2) + { Tick = 0L + Avatar = { Pos = { X = centerX; Y = centerY } } } + + let clamp v lo hi = if v < lo then lo elif v > hi then hi else v + + let step (ts: TimeStep) (world: World) : World = + let maxX = float32 (mapWidthTiles * tilePixels - tilePixels) + let maxY = float32 (mapHeightTiles * tilePixels - tilePixels) + let dx = ts.Input.MoveX * avatarSpeed * ts.Dt + let dy = ts.Input.MoveY * avatarSpeed * ts.Dt + { Tick = world.Tick + 1L + Avatar = + { Pos = + { X = clamp (world.Avatar.Pos.X + dx) 0.0f maxX + Y = clamp (world.Avatar.Pos.Y + dy) 0.0f maxY } } } -- cgit v1.2.3