diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-28 18:48:05 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-28 18:48:05 +0800 |
| commit | d3a2604e30b1deb91afebf550a79cde71bbca6d6 (patch) | |
| tree | 7cf10505e76f5a6749faadb96ff4d678a3c8fb26 /src/LivingVillage.Desktop/Game.fs | |
| parent | 323552b7e49550d378d3871fadcb711c16c71fed (diff) | |
| download | living-village-d3a2604e30b1deb91afebf550a79cde71bbca6d6.tar.gz | |
p42: 启动/菜单水面涟漪整改 — 振幅0.32+波峰列, 帧差14.3, 防降振回归 (leader fix: 提交+推送)
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/Game.fs | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs index 94cc451..121a090 100644 --- a/src/LivingVillage.Desktop/Game.fs +++ b/src/LivingVillage.Desktop/Game.fs @@ -301,6 +301,11 @@ type LivingVillageGame() as this = let mutable p40Step = 0 let mutable p40PendingName = "" let mutable p40Pending = false + // P42 证据钩子:LV_P42_SHOT=1 时拍启动环境动效两帧 + 菜单动效一帧后退出; + // 全程走正常启动/菜单流程(不改 duration/结构/输入),仅按帧表落盘。 + let p42ShotMode = Environment.GetEnvironmentVariable("LV_P42_SHOT") = "1" + let mutable p42SplashEarlyDone = false + let mutable p42SplashLateDone = false let mutable autoplayFrames = 0 let mutable flowStep = 0 let mutable flowHold = 0 @@ -1203,6 +1208,24 @@ type LivingVillageGame() as this = printfn "menu-shot=done frames=%d" menuShotFrame this.Exit() + /// P42 证据:启动环境动效两帧 + 菜单动效一帧,拍完即退出。 + member private this.CaptureP42Shot () = + let save (name: string) = + System.IO.Directory.CreateDirectory recordDirectory |> ignore + this.SaveBackBuffer(sprintf "%s/%s.png" recordDirectory name) + printfn "p42-shot=%s frame=%d" name (if splashActive then splashFrame else menuEntranceFrame) + if splashActive then + if not p42SplashEarlyDone && splashFrame >= P42ShotScript.splashEarlyFrame then + p42SplashEarlyDone <- true + save P42ShotScript.splashEarlyName + if not p42SplashLateDone && splashFrame >= P42ShotScript.splashLateFrame then + p42SplashLateDone <- true + save P42ShotScript.splashLateName + elif menu.Page <> Playing && menuEntranceFrame >= P42ShotScript.menuFrame then + save P42ShotScript.menuName + printfn "p42-shot=done" + this.Exit() + /// P20 证据:把一次 MapGen 绘制渲染到指定尺寸离屏 target,返回绘制瓦片数与纹理。 /// P28:可传入世界 tint 与可选 veil tick(夜景取证用)。 member private this.RenderMapGen (targetWidth: int) (targetHeight: int) (camX: int) (camY: int) (drawFitted: bool) (tint: Color) (veilTick: int64 option) : int * Texture2D = @@ -1445,6 +1468,8 @@ type LivingVillageGame() as this = this.SaveBackBuffer(sprintf "%s/%s%04d.png" recordDirectory recordName recordIndex) if menuShotMode then this.CaptureMenuShot() + if p42ShotMode then + this.CaptureP42Shot() if storyShotMode && storyShotPrepared then storyShotFrame <- storyShotFrame + 1L if not storyShotSaved && storyShotFrame = 20L then @@ -1489,11 +1514,35 @@ type LivingVillageGame() as this = spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, layout.RidgeY + drop, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle (fst TitleScreen.roofSlots), Color.White) spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, layout.EaveY + drop, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle (snd TitleScreen.roofSlots), Color.White) - // 水面色带反射天色,随显现度提高而淡出。 - let waterColor = Color(150, 170, 178, int (255.0f * (1.0f - reveal))) - for row in layout.WaterRows do + // 水面色带反射天色,随显现度提高而淡出;P42 叠加逐格涟漪(相位随帧/列/行)。 + let waterAlpha = int (255.0f * (1.0f - reveal)) + let waterColor = Color(150, 170, 178, waterAlpha) + for (rowIndex, row) in List.indexed layout.WaterRows do for x in 0 .. Sim.tilePixels .. width - 1 do spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, row, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle TitleScreen.waterSlot, waterColor) + for x in 0 .. Sim.tilePixels .. width - 1 do + let column = x / Sim.tilePixels + let brightness = TitleScreen.waterRippleBrightness splashFrame column rowIndex + let crestColor = + Color( + min 255 (int (150.0f * brightness)), + min 255 (int (170.0f * brightness)), + min 255 (int (178.0f * brightness)), + waterAlpha) + let lift = TitleScreen.waterRippleLift splashFrame column rowIndex + spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, row + lift, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle TitleScreen.waterSlot, crestColor) + if TitleScreen.waterRippleCrest splashFrame column rowIndex then + spriteBatch.Draw(pixel, Rectangle(x, row + lift, Sim.tilePixels, 3), Color(225, 240, 245, waterAlpha)) + + // P42 屋檐灯笼呼吸光晕:复用 P14 预乘 alpha 径向路径,随帧与灯序号呼吸。 + let lanternColor, _ = TitleScreen.lanternColors + for (lanternIndex, (lx, ly)) in List.indexed layout.Lanterns do + let breath = TitleScreen.lanternBreathAlpha splashFrame lanternIndex + for (rect, color) in VillageArt.lanternGlowLayers lx ly 28 6 252 216 148 breath do + spriteBatch.Draw(pixel, rect, color) + spriteBatch.Draw(pixel, Rectangle(lx - 3, ly - 5, 8, 10), Color(lanternColor.R, lanternColor.G, lanternColor.B)) + spriteBatch.Draw(pixel, Rectangle(lx - 1, ly - 7, 4, 2), Color(90, 60, 40)) + spriteBatch.Draw(pixel, Rectangle(lx - 2, ly + 5, 6, 2), Color(90, 60, 40)) // 标题:淡入 + 上浮,先画深色投影再画亮面。 let titleRise = int (24.0f * (1.0f - reveal)) @@ -1575,16 +1624,32 @@ type LivingVillageGame() as this = spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, layout.EaveY + skylineDrop, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle (snd TitleScreen.roofSlots), Color.White)) layout.RoofTileSlots - // Water band drawn from the atlas water tile, reflecting the skyline above. - let waterColor = Color(150, 170, 178, int (255.0f * (1.0f - entrance))) - for row in layout.WaterRows do + // Water band drawn from the atlas water tile; P42 adds per-tile ripple. + let waterAlpha = int (255.0f * (1.0f - entrance)) + let waterColor = Color(150, 170, 178, waterAlpha) + for (rowIndex, row) in List.indexed layout.WaterRows do for x in 0 .. Sim.tilePixels .. width - 1 do spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, row, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle TitleScreen.waterSlot, waterColor) - - // Lantern glows along the water bank. - let lanternColor, lanternHalo = TitleScreen.lanternColors - for (lx, ly) in layout.Lanterns do - spriteBatch.Draw(pixel, Rectangle(lx - 8, ly - 8, 24, 24), Color(lanternHalo.R, lanternHalo.G, lanternHalo.B, 70)) + for x in 0 .. Sim.tilePixels .. width - 1 do + let column = x / Sim.tilePixels + let brightness = TitleScreen.waterRippleBrightness menuEntranceFrame column rowIndex + let crestColor = + Color( + min 255 (int (150.0f * brightness)), + min 255 (int (170.0f * brightness)), + min 255 (int (178.0f * brightness)), + waterAlpha) + let lift = TitleScreen.waterRippleLift menuEntranceFrame column rowIndex + spriteBatch.Draw(artTextures.TileAtlas, Rectangle(x, row + lift, Sim.tilePixels, Sim.tilePixels), VillageArt.atlasTileRectangle TitleScreen.waterSlot, crestColor) + if TitleScreen.waterRippleCrest menuEntranceFrame column rowIndex then + spriteBatch.Draw(pixel, Rectangle(x, row + lift, Sim.tilePixels, 3), Color(225, 240, 245, waterAlpha)) + + // P42 bank lanterns breathe through the shared P14 premultiplied-alpha radial path. + let lanternColor, _ = TitleScreen.lanternColors + for (lanternIndex, (lx, ly)) in List.indexed layout.Lanterns do + let breath = TitleScreen.lanternBreathAlpha menuEntranceFrame lanternIndex + for (rect, color) in VillageArt.lanternGlowLayers lx ly 28 6 252 216 148 breath do + spriteBatch.Draw(pixel, rect, color) spriteBatch.Draw(pixel, Rectangle(lx - 3, ly - 5, 8, 10), Color(lanternColor.R, lanternColor.G, lanternColor.B)) spriteBatch.Draw(pixel, Rectangle(lx - 1, ly - 7, 4, 2), Color(90, 60, 40)) spriteBatch.Draw(pixel, Rectangle(lx - 2, ly + 5, 6, 2), Color(90, 60, 40)) |
