diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 15:06:03 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 15:06:03 +0800 |
| commit | 87aa4594ffe395318364feae9fd157d52b60a082 (patch) | |
| tree | 099b328b7996a98cd5e26631508bedb5a0d15ed3 /src/LivingVillage.Desktop/Game.fs | |
| parent | ab19df0ebad8da972cd30f89f7cfd8ef38b8c0ae (diff) | |
| download | living-village-87aa4594ffe395318364feae9fd157d52b60a082.tar.gz | |
feat(desktop): 512x384 程序生成地图与巡游取证模式
ProceduralMap 纯函数生成器:splitmix64 随机游走河道(三条西→东,宽 3,穿核心禁入)、三倍频值噪声草地/泥炭变化、泊松式最小距离布点(800 次尝试),村核矩形(24..38 x 16..34)由生成器不变式保证可通行;VillageArt 于大世界模式下按 terrain code 逐格绘制(可视化范围裁剪,无每帧分配);Game 新增 LV_MAP_SCALE(默认 1,表示规模倍数)与 LV_MAP_TOUR 巡游采样(八个地标位置含角/中心/河带);快照回归断言:同 seed 逐字节一致、异 seed 必然差异、核心矩形无水面。
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/Game.fs | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs index 79c6fec..ab9b628 100644 --- a/src/LivingVillage.Desktop/Game.fs +++ b/src/LivingVillage.Desktop/Game.fs @@ -149,8 +149,25 @@ type LivingVillageGame() as this = let mutable pauseHelpControl: SimulationControl option = None let recordMode = Environment.GetEnvironmentVariable("LV_AUTOPLAY_RECORD") = "1" let mutable recordIndex = 0 + let mutable scale = int ( + match Environment.GetEnvironmentVariable("LV_MAP_SCALE") with + | null | "" -> 1 + | v -> match Int32.TryParse v with (true, value) -> max 1 value | _ -> 1) + let mapTourMode = Environment.GetEnvironmentVariable("LV_MAP_TOUR") = "1" + let mutable tourWaypoints = + [ (1, 1); (255, 191); (509, 381); (256, 60); (256, 300); (80, 200); (430, 300) ] + let mutable tourIndex = 0 + let mutable tourFrame = 0 do + if scale > 1 then + Sim.configureBounds (64 * scale) (48 * scale) + ProceduralMap.activate (uint64 4242) + if mapTourMode then + tourWaypoints <- + [ (1, 1); (Sim.mapWidthTiles / 2, Sim.mapHeightTiles / 2); (Sim.mapWidthTiles - 3, Sim.mapHeightTiles - 3) + (Sim.mapWidthTiles / 2, 60); (Sim.mapWidthTiles / 2, Sim.mapHeightTiles - 60) + (80, 200); (430, 300) ] graphics.PreferredBackBufferWidth <- 1280 graphics.PreferredBackBufferHeight <- 720 graphics.SynchronizeWithVerticalRetrace <- true @@ -272,8 +289,32 @@ type LivingVillageGame() as this = printfn (if nextState.TimedOut then "sample result=timeout" else "sample result=ok") this.Exit() + member private this.RunMapTour () = + let (tileX, tileY) = tourWaypoints.[tourIndex % tourWaypoints.Length] + let position : Vec2 = + { X = float32 (tileX * Sim.tilePixels + Sim.tilePixels / 2) + Y = float32 (tileY * Sim.tilePixels + Sim.tilePixels / 2) } + world <- { world with Avatar = { world.Avatar with Pos = position } } + // give NPCs active ticks so the town stays alive between waypoints + for _ in 0 .. 7 do + world <- Sim.step { Input = { MoveX = 0.0f; MoveY = 0.0f } } world + avatarFacing <- VillageArt.SouthFacing + m5View <- M5Interaction.refreshPrompt world m5View + this.CenterCamera() + tourFrame <- tourFrame + 1 + if tourFrame >= 45 then + tourFrame <- 0 + tourIndex <- tourIndex + 1 + if tourIndex >= tourWaypoints.Length then + printfn "map tour=complete frames={recordIndex}" + this.Exit() + else + printfn $"map tour={tourIndex} at tile=({tileX},{tileY})" + member private this.UpdatePlaying (gameTime: GameTime) (kb: KeyboardState) (pressed: Keys -> bool) (pressedAny: Keys list -> bool) = - if sampleMode then + if mapTourMode then + this.RunMapTour() + elif sampleMode then this.RunSampleMode() else this.UpdatePlayingManual gameTime kb pressed pressedAny |
