blob: 65300f0ae8f6ecdd82bf0d73076406cf85308d2c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
namespace LivingVillage.Desktop
open Microsoft.Xna.Framework
open LivingVillage.Kernel
open LivingVillage.Kernel.Sim
type M6DayNight =
| Day
| Night
type M6RenderProfile =
{ Mode: M6DayNight
Background: Color
WorldTint: Color
Blend: float32
LanternGlow: float32 }
module M6Presentation =
let dayNightLabel mode : string =
match mode with
| Day -> "白天"
| Night -> "夜晚"
/// Continuous light blend: 0 = full day, 1 = full night. Ramps are deterministic
/// pure functions of the simulation tick (dawn 4:00-6:00, dusk 20:00-22:00), so the
/// boundaries agree with Sim.isNightTick (night >= 22:00 or < 6:00).
let lightingBlend (tick: int64) : float32 =
let hourTicks = Sim.ticksPerDay / 24L
let hour = float32 (tick / hourTicks)
let clamp01 v = if v < 0.0f then 0.0f elif v > 1.0f then 1.0f else v
if hour >= 6.0f && hour < 20.0f then 0.0f
elif hour >= 22.0f then 1.0f
elif hour < 4.0f then 1.0f
elif hour < 6.0f then clamp01 (1.0f - (hour - 4.0f) / 2.0f)
else clamp01 ((hour - 20.0f) / 2.0f)
let private lerp (a: int) (b: int) (blend: float32) : int =
a + int (float32 (b - a) * blend)
let backgroundAtBlend (blend: float32) : Color =
Color(lerp 100 18 blend, lerp 160 25 blend, lerp 210 55 blend)
let worldTintAtBlend (blend: float32) : Color =
Color(lerp 255 118 blend, lerp 248 136 blend, lerp 224 184 blend)
/// Pure day-phase lighting: deterministic tint/background plus lantern warm-glow boost.
let lightingAtTick (tick: int64) : M6RenderProfile =
let blend = lightingBlend tick
{ Mode = if blend < 0.5f then Day else Night
Background = backgroundAtBlend blend
Blend = blend
WorldTint = worldTintAtBlend blend
LanternGlow = blend }
let profileAtTick (tick: int64) : M6RenderProfile = lightingAtTick tick
let clockLabel (control: SimulationControl) : string =
if control.Paused then
"暂停"
else
match control.Speed with
| OneX -> "1倍速"
| TwoX -> "2倍速"
| FiveX -> "5倍速"
/// 倍速标签(语义别名,HUD 用)。
let speedLabel (control: SimulationControl) : string = clockLabel control
let private hourOf (tick: int64) : int =
int ((tick / (Sim.ticksPerDay / 24L)) % 24L)
/// 24 小时制的模拟时钟(HH:MM),由 tick 纯函数导出。
let clockTimeLabel (tick: int64) : string =
let hourTicks = Sim.ticksPerDay / 24L
let hour = hourOf tick
let minute = int ((tick % hourTicks) * 60L / hourTicks)
sprintf "%02d:%02d" hour minute
/// 时段标签:清晨/白天/黄昏/夜晚,与实际 tick 一致(纯函数)。
let timePeriodLabel (tick: int64) : string =
let hour = hourOf tick
if hour < 5 then "夜晚"
elif hour < 8 then "清晨"
elif hour < 17 then "白天"
elif hour < 20 then "黄昏"
else "夜晚"
|