diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 12:10:42 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 12:10:42 +0800 |
| commit | a70a057fce7afa5787b2d4a037d7016f1120ef6a (patch) | |
| tree | ce5a24cf07dbbfd46cee48cbec561cc23349f48e /src/LivingVillage.Desktop/Game.fs | |
| parent | 3cd5a635d12474647c4cf288a5cc4acb4e0eb1b5 (diff) | |
| download | living-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.fs | 50 |
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 |
