summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/Game.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 12:10:42 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 12:10:42 +0800
commita70a057fce7afa5787b2d4a037d7016f1120ef6a (patch)
treece5a24cf07dbbfd46cee48cbec561cc23349f48e /src/LivingVillage.Desktop/Game.fs
parent3cd5a635d12474647c4cf288a5cc4acb4e0eb1b5 (diff)
downloadliving-village-a70a057fce7afa5787b2d4a037d7016f1120ef6a.tar.gz
feat(desktop): P29 512 聚落组团 + 夜景灯光径向光晕
- MapGen:仅大图新增 ClusterSeed(group seeding)与组团布屋——512 沿横向石板路 (主街+河岸路)成排成组:组内 2-4 座/1 格间隙、组间 4-6 格空档,宽度 2/3/4 分层; 垂柳改为确定性成丛(2-3 株/丛、丛间 3-5 格空档)。独立 clusterRng 不触碰 structureRng,默认图仍不消费 RNG,64x48=6042052 / 256x192=1284656962 锁定不变。 - VillageArt:新增 lanternFalloff(二次 1-(d/r)^2,半径 0 处最大、边缘 0、严格单调无平台); lanternGlowLayers 按该衰减逐环累积 alpha;drawNightGlows 对桥头灯笼+民居门窗画半径 4 tile 的柔和径向光晕,整图取证与实机 DrawWorldView 共用同一套纯函数。 - 回归 +6:组团行/成丛/衰减/光源确定性;Desktop 151、Kernel 92 全绿,Release 0/0, final_digest=953775FAEB2F… 3 次一致。证据帧见 art/p29-*。
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
-rw-r--r--src/LivingVillage.Desktop/Game.fs50
1 files changed, 27 insertions, 23 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs
index 38d9e94..5f6e99e 100644
--- a/src/LivingVillage.Desktop/Game.fs
+++ b/src/LivingVillage.Desktop/Game.fs
@@ -880,11 +880,16 @@ type LivingVillageGame() as this =
this.GraphicsDevice.SetRenderTarget target
this.GraphicsDevice.Clear(Color(18, 26, 20))
spriteBatch.Begin()
+ // P29:夜景取证帧与真实渲染同一套灯光衰减——按 veil tick 的 LanternGlow 叠加柔和径向光晕。
+ let glowScale =
+ match veilTick with
+ | Some tick -> (M6Presentation.profileAtTick tick).LanternGlow
+ | None -> 0.0f
let drawn =
if drawFitted then
- VillageArt.drawMapFitted spriteBatch artTextures pixel targetWidth targetHeight mapGenResult tint
+ VillageArt.drawMapFitted spriteBatch artTextures pixel targetWidth targetHeight mapGenResult tint glowScale
else
- VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) targetWidth targetHeight mapGenResult 0L tint
+ VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) targetWidth targetHeight mapGenResult 0L tint glowScale
// 与 DrawWorldView 同一套纯函数 veil,保证取证夜景=真实渲染夜景。
match veilTick with
| Some tick ->
@@ -958,7 +963,7 @@ type LivingVillageGame() as this =
this.GraphicsDevice.SetRenderTarget frameTarget
for _ in 1 .. 30 do
spriteBatch.Begin()
- VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) viewport.Width viewport.Height mapGenResult 0L Color.White |> ignore
+ VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) viewport.Width viewport.Height mapGenResult 0L Color.White 0.0f |> ignore
spriteBatch.End()
this.GraphicsDevice.SetRenderTarget null
frameWatch.Stop()
@@ -1181,29 +1186,28 @@ type LivingVillageGame() as this =
world.Tick
profile.WorldTint
- // Warm lantern glows strengthen as night falls (pure function of tick phase).
- // Concentric premultiplied circles fall off radially from each lantern tile, so
- // the core stays a soft warm disc instead of saturating into a white block, and
- // no glow is painted where there is no lantern entity. 生成器世界用桥头灯笼。
+ // 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
+ // is painted where there is no light entity. 生成器世界用桥头灯笼 + 民居门窗。
if profile.LanternGlow > 0.3f then
let glow = profile.LanternGlow
let peakAlpha = int (140.0f * glow)
- let lanternTiles =
- match riverscapeMap with
- | Some map -> VillageArt.bridgeLanternTiles map
- | None ->
- renderPlan.Props
- |> List.choose (fun prop ->
- match prop.Kind with
- | VillageArt.RenderPropKind.RiverLantern ->
- let position = VillageArt.worldTile renderPlan prop.Position
- Some(position.X, position.Y)
- | _ -> None)
- for (tileX, tileY) in lanternTiles do
- let centerX = tileX * Sim.tilePixels - int camera.X + Sim.tilePixels / 2
- let centerY = tileY * Sim.tilePixels - int camera.Y + Sim.tilePixels / 2
- for (rect, color) in VillageArt.lanternGlowLayers centerX centerY 44 6 255 214 150 peakAlpha do
- spriteBatch.Draw(pixel, rect, color)
+ let tileX x = x * Sim.tilePixels - int camera.X
+ let tileY y = y * Sim.tilePixels - int camera.Y
+ match riverscapeMap with
+ | Some map ->
+ VillageArt.drawNightGlows spriteBatch pixel map (4 * Sim.tilePixels) (int (150.0f * glow)) tileX tileY Sim.tilePixels
+ | None ->
+ for prop in renderPlan.Props do
+ match prop.Kind with
+ | VillageArt.RenderPropKind.RiverLantern ->
+ let position = VillageArt.worldTile renderPlan prop.Position
+ let centerX = tileX position.X + Sim.tilePixels / 2
+ let centerY = tileY position.Y + Sim.tilePixels / 2
+ for (rect, color) in VillageArt.lanternGlowLayers centerX centerY (3 * Sim.tilePixels) 8 255 214 150 peakAlpha do
+ spriteBatch.Draw(pixel, rect, color)
+ | _ -> ()
VillageArt.drawGroundShadow spriteBatch pixel camera world.Avatar.Pos
let avatarSpec = VillageArt.avatarSpriteSpec avatarFacing avatarMoving world.Tick