summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Kernel/Sim.fs
blob: 0e3683b0e53a50af9426d83ed49409caceb97ff7 (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
namespace LivingVillage.Kernel

module Sim =

    [<Struct>]
    type Vec2 =
        { X: float32
          Y: float32 }

    [<Struct>]
    type Avatar =
        { Pos: Vec2 }

    type Input =
        { MoveX: float32
          MoveY: float32 }

    type TimeStep =
        { Input: Input }

    [<Struct>]
    type NoHost =
        { Reserved: uint64 }

    [<Struct>]
    type World =
        { Tick: int64
          Time: float
          Rng: RngState
          Avatar: Avatar
          NoHost: NoHost }

    let ticksPerSecond = 60L
    let secondsPerDay = 86400L
    let ticksPerDay = secondsPerDay * ticksPerSecond
    let dtSeconds = 1.0 / float ticksPerSecond
    let dtSecondsF = 1.0f / float32 ticksPerSecond

    let mapWidthTiles = 64
    let mapHeightTiles = 48
    let tilePixels = 32
    let avatarSpeed = 160.0f

    let initialWorld (seed: uint64) : World =
        let centerX = float32 (mapWidthTiles * tilePixels / 2 - tilePixels / 2)
        let centerY = float32 (mapHeightTiles * tilePixels / 2 - tilePixels / 2)
        { Tick = 0L
          Time = 0.0
          Rng = Rng.ofSeed seed
          Avatar = { Pos = { X = centerX; Y = centerY } }
          NoHost = { Reserved = 0UL } }

    let clamp v lo hi = if v < lo then lo elif v > hi then hi else v

    let step (ts: TimeStep) (world: World) : World =
        let tick = world.Tick + 1L
        let maxX = float32 (mapWidthTiles * tilePixels - tilePixels)
        let maxY = float32 (mapHeightTiles * tilePixels - tilePixels)
        let dx = ts.Input.MoveX * avatarSpeed * dtSecondsF
        let dy = ts.Input.MoveY * avatarSpeed * dtSecondsF
        { Tick = tick
          Time = float tick * dtSeconds
          Rng = world.Rng
          Avatar =
            { Pos =
                { X = clamp (world.Avatar.Pos.X + dx) 0.0f maxX
                  Y = clamp (world.Avatar.Pos.Y + dy) 0.0f maxY } }
          NoHost = world.NoHost }