aboutsummaryrefslogtreecommitdiff
path: root/src/Update/CloudUpdate.elm
blob: d8ccf3658b18df0336935dc9d1ea3dcad83cd4ce (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
module Update.CloudUpdate exposing
  ( cloudUpdate
  )

import List
import List.Nonempty as NE exposing (Nonempty(..), (:::))
import Random.Pcg as Random exposing (Seed, Generator)

import Model.Vec2 exposing (..)
import Model.Player exposing (..)
import Model.Board exposing (boardDiagonal)
import Model.Point exposing (..)
import Model.Cloud exposing (..)
import Model.Config exposing (..)
import Model.Level exposing (..)

import Utils.Geometry exposing (..)

cloudUpdate : Float -> Vec2 -> Seed -> Player -> Float -> Cloud -> Int -> (Cloud, Int, Seed)
cloudUpdate elapsedTime boardSize seed player playerSize {points, spawn, lastSpawn} currentScore =
  let pointsToCatch = presentPoints elapsedTime boardSize (points player.config)
      presentAndNotCaughtPoints = List.filter (not << (playerPointCollision elapsedTime player playerSize)) pointsToCatch
      addScore = (List.length pointsToCatch) - (List.length presentAndNotCaughtPoints)
      presentOtherPoints = presentPoints elapsedTime boardSize (points (otherConfig player.config))
      (newCloud, seed') =
        if elapsedTime > lastSpawn + spawn then
          let (newPoint1, seed') = getNewPoint elapsedTime boardSize seed currentScore
              (newPoint2, seed'') = getNewPoint elapsedTime boardSize seed' currentScore
          in  ( { points = \config ->
                    if(config == player.config)
                      then
                        newPoint1 :: presentAndNotCaughtPoints
                      else
                        newPoint2 :: presentOtherPoints
                , spawn = spawn - sqrt(spawn) / 50
                , lastSpawn = elapsedTime
                }
              , seed''
              )
        else
          ( { points = \config ->
                if(config == player.config) then
                  presentAndNotCaughtPoints
                else
                  presentOtherPoints
            , spawn = spawn
            , lastSpawn = lastSpawn
            }
          , seed
          )
  in  (newCloud, addScore, seed')

presentPoints : Float -> Vec2 -> List Point -> List Point
presentPoints elapsedTime boardSize points =
  let isPresent point = (distance (pointMove point elapsedTime) originVec) < (pointAwayDist boardSize)
  in  List.filter isPresent points

getNewPoint : Float -> Vec2 -> Seed -> Int -> (Point, Seed)
getNewPoint elapsedTime boardSize seed currentScore =
  let (initPos, seed') = pointInitPos boardSize seed
      (initDest, seed'') = pointDestination boardSize seed'
      (randomMove, seed''') = Random.step (nonemptySample << .moves <| currentLevel currentScore) seed''
  in  ( { initTime = elapsedTime
        , initPos = initPos
        , initDest = initDest
        , move = \initTime initPos initDest elapsedTime ->
            let delta = elapsedTime - initTime
                move = randomMove initPos initDest delta
            in  initPos `add` move
        }
      , seed'''
      )

nonemptySample : Nonempty a -> Random.Generator a
nonemptySample nonempty =
  Random.int 0 (NE.length nonempty - 1)
    |> Random.map (\i -> NE.get i nonempty)

pointInitPos : Vec2 -> Seed -> (Vec2, Seed)
pointInitPos boardSize seed =
  let (rand, seed') = Random.step (Random.float 0 1) seed
      angle = rand * (degrees 360)
      dist = pointSpawnDist boardSize
  in  (polarToCartesian angle dist, seed')

pointDestination : Vec2 -> Seed -> (Vec2, Seed)
pointDestination boardSize seed =
  case Random.step (Random.list 4 (Random.float 0 1)) seed of
    ([r1, r2, r3, r4], seed') ->
      ( randomBoardPosition boardSize (r1, r2) (r3, r4)
      , seed'
      )
    _ ->
      ( randomBoardPosition boardSize (0, 0) (0, 0)
      , seed
      )

randomBoardPosition : Vec2 -> (Float, Float) -> (Float, Float) -> Vec2
randomBoardPosition boardSize (randomX, randomY) (percentX, percentY) =
  let width = boardSize.x * percentX
      height = boardSize.y * percentY
  in  { x = width * randomX - width / 2
      , y = height * randomY - height / 2
      }