diff options
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/Game.fs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs index 578be72..a187cc4 100644 --- a/src/LivingVillage.Desktop/Game.fs +++ b/src/LivingVillage.Desktop/Game.fs @@ -331,6 +331,11 @@ type LivingVillageGame() as this = let mutable p46CloudLateDone = false let mutable p46MenuADone = false let mutable p46MenuBDone = false + // P47 证据钩子:LV_P47_SHOT=1 时在真实生成器世界里拍「白天河道 / 夜晚河道 / 近景」三帧。 + let p47ShotMode = Environment.GetEnvironmentVariable("LV_P47_SHOT") = "1" + let mutable p47Step = 0 + let mutable p47PendingName = "" + let mutable p47Pending = false let mutable autoplayFrames = 0 let mutable flowStep = 0 let mutable flowHold = 0 @@ -986,6 +991,88 @@ type LivingVillageGame() as this = else p46MenuBDone <- true save p46PendingName + /// P47 证据:真实生成器世界里拍「白天河道 / 夜晚河道 / 近景」三帧,含 P47 场景细节。 + member private this.PrepareP47Shot () = + let setHour (hour: float) = + let tick = M6Presentation.resolveStartTick (Some hour) false + world <- { world with Tick = tick; Time = float tick * Sim.dtSeconds } + let placeCameraOn (tileX: int) (tileY: int) = + world <- { world with Avatar = { world.Avatar with Pos = { X = float32 (tileX * Sim.tilePixels); Y = float32 (tileY * Sim.tilePixels) } } } + this.CenterCamera() + if not p47Pending then + match riverscapeMap with + | None -> this.Exit() + | Some map -> + let riverside = + // 取第一处「光源正下方有水面」的倒影点,相机对准其光源格,倒影落在正下方。 + match SceneDetail.reflectionStreaks map with + | (rx, ry, _) :: _ -> (rx, ry - 1) + | [] -> + match VillageArt.cc0LanternTiles map 12 with + | (lx, ly) :: _ -> (lx, ly) + | [] -> + match map.Bridges |> List.sortBy (fun (x, y) -> (x, y)) |> List.tryHead with + | Some (bx, by) -> (bx, by) + | None -> (map.Core.MinX, map.Core.MinY) + let closeup = + match SceneDetail.floatingProps map with + | (fx, fy, _) :: _ -> (fx, fy) + | [] -> riverside + let reportVisibleReflections () = + let vw = this.GraphicsDevice.Viewport.Width + let vh = this.GraphicsDevice.Viewport.Height + for (lx, ly) in SceneDetail.lightSourceTiles map do + for d in 1 .. SceneDetail.reflectionRange do + let ry = ly + d + if SceneDetail.isWater map lx ry then + let ssx = lx * Sim.tilePixels - int camera.X + let ssy = ly * Sim.tilePixels - int camera.Y + let rsx = lx * Sim.tilePixels - int camera.X + let rsy = ry * Sim.tilePixels - int camera.Y + if ssx >= 0 && ssx + Sim.tilePixels <= vw && ssy >= 0 && ssy + Sim.tilePixels <= vh + && rsy + Sim.tilePixels <= vh then + printfn + "p47-reflection src=%d,%d dst=%d,%d alpha=%d" + ssx ssy rsx rsy (SceneDetail.reflectionAlphaAt d) + printfn + "p47-elements reeds=%d floats=%d reflections=%d sources=%d" + (List.length (SceneDetail.bankReedTiles map)) + (List.length (SceneDetail.floatingProps map)) + (List.length (SceneDetail.reflectionStreaks map)) + (List.length (SceneDetail.lightSourceTiles map)) + match p47Step with + | 0 -> + setHour 12.0 + placeCameraOn (fst riverside) (snd riverside) + reportVisibleReflections () + p47PendingName <- "p47-day" + p47Pending <- true + | 1 -> + setHour 23.5 + placeCameraOn (fst riverside) (snd riverside) + reportVisibleReflections () + p47PendingName <- "p47-night" + p47Pending <- true + | 2 -> + setHour 12.0 + placeCameraOn (fst closeup) (snd closeup) + reportVisibleReflections () + p47PendingName <- "p47-close" + p47Pending <- true + | _ -> + printfn "p47-shot=done" + this.Exit() + + /// P47 证据:在 `Draw` 末尾落盘当前后台缓冲。 + member private this.CaptureP47Shot () = + if p47Pending then + p47Pending <- false + System.IO.Directory.CreateDirectory recordDirectory |> ignore + this.SaveBackBuffer(sprintf "%s/%s.png" recordDirectory p47PendingName) + printfn "p47-shot=%s tick=%d pos=(%.0f,%.0f) camera=(%.0f,%.0f)" + p47PendingName world.Tick world.Avatar.Pos.X world.Avatar.Pos.Y camera.X camera.Y + p47Step <- p47Step + 1 + /// P46 证据:菜单阶段按帧表把 menuEntranceFrame 钉到灯笼呼吸的波峰/波谷,拍两相位。 member private this.PrepareP46Shot () = if p46MenuADone && p46MenuBDone then @@ -1385,6 +1472,14 @@ type LivingVillageGame() as this = elif p46ShotMode then if menu.Page = MainMenu then this.PrepareP46Shot() + elif p47ShotMode 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.PrepareP47Shot() elif menu.Page = Playing then this.UpdatePlaying gameTime kb pressed pressedAny elif menuShotMode then @@ -1796,6 +1891,8 @@ type LivingVillageGame() as this = this.CaptureP45Shot() if p46ShotMode then this.CaptureP46Shot() + if p47ShotMode && menu.Page = Playing then + this.CaptureP47Shot() /// 启动画面:分层天色 + 屋脊/水面剪影 + 标题淡入上浮 + 跳过提示,全部为帧计数纯函数。 member private this.DrawSplash() = @@ -2047,6 +2144,20 @@ type LivingVillageGame() as this = world.Tick profile.WorldTint + // P47 场景细节:河道倒影 + 岸边芦苇加密度 + 漂浮元素 + 近景楼层层错落(统一光源阴影)。 + match riverscapeMap with + | Some map -> + SceneDetailRender.draw + spriteBatch + artTextures + pixel + camera + viewport.Width + viewport.Height + map + world.Tick + | None -> () + // Warm lantern / window glows strengthen as night falls (pure function of tick phase). // Concentric premultiplied circles follow a quadratic radial falloff (radius 3-4 tiles), // so the core stays a soft warm disc instead of saturating to a white block and no glow |
