diff options
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/Game.fs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs index e5f2c11..6b52225 100644 --- a/src/LivingVillage.Desktop/Game.fs +++ b/src/LivingVillage.Desktop/Game.fs @@ -331,6 +331,12 @@ type LivingVillageGame() as this = let mutable p62PendingName = "" let mutable p62Pending = false let mutable p62MoveFrames = 0 + // P64 证据钩子(A3 成熟度):俯瞰/桥近景/内景三帧,内景走真实 MoveTo + Interact。 + let p64ShotMode = Environment.GetEnvironmentVariable("LV_P64_SHOT") = "1" + let mutable p64Step = 0 + let mutable p64PendingName = "" + let mutable p64Pending = false + let mutable p64MoveFrames = 0 // P45 证据钩子:LV_P45_SHOT=1 时拍角色 idle / 行走朝下 / 行走朝右 三帧(真实游戏截图)。 let p45ShotMode = Environment.GetEnvironmentVariable("LV_P45_SHOT") = "1" let mutable p45Step = 0 @@ -1070,6 +1076,88 @@ type LivingVillageGame() as this = p62PendingName world.Tick world.Avatar.Pos.X world.Avatar.Pos.Y camera.X camera.Y m5View.HomeMode p62Step <- p62Step + 1 + /// P64 证据(A3 成熟度):样板区俯瞰 / 桥近景 / 内景三帧。 + /// 内景沿用 P62 的真实 MoveTo + Interact 进门路径;桥为既有位置,只增强可读性。 + member private this.PrepareP64Shot () = + let tileCenter (t: TilePosition) : Vec2 = + { X = float32 (t.X * Sim.tilePixels + Sim.tilePixels / 2) + Y = float32 (t.Y * Sim.tilePixels + Sim.tilePixels / 2) } + let sceneCenter localX localY = + tileCenter (worldTileForSceneTile { X = localX; Y = localY }) + let home = VillagePresentation.scene.Homes |> List.head + let doorCenter = sceneCenter home.Door.X home.Door.Y + let setHour (hour: float) = + let tick = M6Presentation.resolveStartTick (Some hour) false + world <- { world with Tick = tick; Time = float tick * Sim.dtSeconds } + if not p64Pending then + match p64Step with + | 0 -> + setHour 12.0 + // 俯瞰:整村居中,上半部补种与桥、民居同框。 + world <- { world with Avatar = { world.Avatar with Pos = sceneCenter 6 3 } } + this.CenterCamera() + let plan = VillageArt.sampleRenderPlan () + let upper = + plan.Props + |> List.filter (fun prop -> prop.Kind <> VillageArt.House && prop.Position.Y >= 0 && prop.Position.Y <= 6) + let upperKinds = upper |> List.map (fun prop -> prop.Kind) |> List.distinct |> List.length + let bridgeProps = plan.Props |> List.filter (fun prop -> prop.Kind = VillageArt.Bridge) |> List.length + let abutments = VillageArt.sampleBridgeAbutmentTiles plan |> List.length + printfn + "p64-plan upper_band_props=%d upper_band_kinds=%d bridge_props=%d bridge_foot_tiles=3 bridge_abutments=%d interior_elements=%d" + upper.Length + upperKinds + bridgeProps + abutments + plan.Interior.Elements.Length + p64PendingName <- "p64-overview" + p64Pending <- true + | 1 -> + setHour 12.0 + // 桥近景:角色立于桥北岸,相机居中,桥面栏杆/护岸石入画。 + world <- { world with Avatar = { world.Avatar with Pos = sceneCenter 6 10 } } + this.CenterCamera() + p64PendingName <- "p64-bridge" + p64Pending <- true + | 2 -> + // 真实走入:沿真实 Sim.step 向门口移动,抵达后真实 Interact 进门。 + let dx = doorCenter.X - world.Avatar.Pos.X + let dy = doorCenter.Y - world.Avatar.Pos.Y + if dx * dx + dy * dy <= 12.0f * 12.0f then + let nextWorld, nextView = M5Interaction.apply M5Command.Interact world m5View + world <- nextWorld + m5View <- nextView + match m5View.HomeMode with + | Inside _ -> + p64PendingName <- "p64-interior" + p64Pending <- true + | Outside -> + p64MoveFrames <- p64MoveFrames + 1 + else + let length = sqrt (dx * dx + dy * dy) + let input = + if length > 0.001f then { MoveX = dx / length; MoveY = dy / length } + else { MoveX = 0.0f; MoveY = 0.0f } + world <- Sim.step { Input = input } world + p64MoveFrames <- p64MoveFrames + 1 + if p64MoveFrames > 900 then + printfn "p64-shot=move-timeout frames=%d home=%A" p64MoveFrames m5View.HomeMode + this.Exit() + | _ -> + printfn "p64-shot=done" + this.Exit() + + /// P64 证据:落盘并打印帧名/相机/内景模式,供 analyze 核验。 + member private this.CaptureP64Shot () = + if p64Pending then + p64Pending <- false + System.IO.Directory.CreateDirectory recordDirectory |> ignore + this.SaveBackBuffer(sprintf "%s/%s.png" recordDirectory p64PendingName) + printfn + "p64-shot=%s tick=%d avatar=(%.0f,%.0f) camera=(%.0f,%.0f) home=%A" + p64PendingName world.Tick world.Avatar.Pos.X world.Avatar.Pos.Y camera.X camera.Y m5View.HomeMode + p64Step <- p64Step + 1 + member private this.PrepareP45Shot () = let baseTick = M6Presentation.resolveStartTick (Some 12.0) false let setTick (tick: int64) = @@ -2067,6 +2155,14 @@ type LivingVillageGame() as this = else this.DispatchMenuInput Confirm elif menu.Page = Playing then this.PrepareP62Shot() + elif p64ShotMode then + if menu.Page = MainMenu then + this.DispatchMenuInput Confirm + elif menu.Page = OccupationSelect then + if menu.Selected <> 0 then this.DispatchMenuInput Down + else this.DispatchMenuInput Confirm + elif menu.Page = Playing then + this.PrepareP64Shot() elif p45ShotMode then if menu.Page = MainMenu then this.DispatchMenuInput Confirm @@ -2541,6 +2637,8 @@ type LivingVillageGame() as this = this.CaptureP61Shot() if p62ShotMode && menu.Page = Playing then this.CaptureP62Shot() + if p64ShotMode && menu.Page = Playing then + this.CaptureP64Shot() if p45ShotMode && menu.Page = Playing then this.CaptureP45Shot() if p46ShotMode then |
