summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/TitleScreen.fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Desktop/TitleScreen.fs')
-rw-r--r--src/LivingVillage.Desktop/TitleScreen.fs32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/TitleScreen.fs b/src/LivingVillage.Desktop/TitleScreen.fs
index 0dcd693..2e760ef 100644
--- a/src/LivingVillage.Desktop/TitleScreen.fs
+++ b/src/LivingVillage.Desktop/TitleScreen.fs
@@ -88,6 +88,38 @@ module TitleScreen =
if frameCount >= 120L then 0.0f
else 1.0f - float32 frameCount / 120.0f
+ // ---- P42 environment FX: all pure functions of the frame counter, so re-rendering
+ // the same frame is byte-identical. Shared by the splash and the start menu. ----
+
+ /// Sine ripple amplitude of the water band. Kept as a named constant so a test can
+ /// assert it never regresses below the full-frame visibility budget (>= 0.25).
+ let waterRippleAmplitude = 0.32f
+
+ /// Water ripple phase: moves with the frame and is dense across tile columns
+ /// (~5 tiles per wave), so adjacent 28px columns differ enough to read at 1x.
+ let waterRipplePhase (frame: int64) (column: int) (rowIndex: int) : float32 =
+ float32 (frame % 4096L) / 5.0f + float32 column * 1.25f + float32 rowIndex * 0.6f
+
+ /// Water ripple brightness per tile column: base 1.0 +/- waterRippleAmplitude sine.
+ let waterRippleBrightness (frame: int64) (column: int) (rowIndex: int) : float32 =
+ 1.0f + waterRippleAmplitude * sin (waterRipplePhase frame column rowIndex)
+
+ /// Water crest lift in whole pixels (-2..2) for a tile column; drives the moving
+ /// ripple highlight without ever leaving a hole in the water band.
+ let waterRippleLift (frame: int64) (column: int) (rowIndex: int) : int =
+ int (System.Math.Round(float (sin (waterRipplePhase frame column rowIndex) * 2.0f), System.MidpointRounding.AwayFromZero))
+
+ /// True on columns sitting on a wave crest; the renderer caps these with a bright
+ /// highlight and the frame analysis counts them.
+ let waterRippleCrest (frame: int64) (column: int) (rowIndex: int) : bool =
+ sin (waterRipplePhase frame column rowIndex) > 0.55f
+
+ /// Eave-lantern breathing glow alpha, bounded to [40, 96]; phase moves with the
+ /// frame and the lantern index so the bank lanterns breathe out of step.
+ let lanternBreathAlpha (frame: int64) (index: int) : int =
+ let phase = float32 (frame % 4096L) / 22.0f + float32 index * 1.3f
+ 68 + int (System.Math.Round(float (sin phase * 28.0f), System.MidpointRounding.AwayFromZero))
+
let layout (viewportWidth: int) (viewportHeight: int) : TitleLayout =
let width = max 320 viewportWidth
let height = max 240 viewportHeight