aboutsummaryrefslogtreecommitdiff
path: root/src/Update/CloudUpdate.elm
blob: 1fbb9d3ef7e5fe83d93f94827715183ba14c90b1 (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
105
106
107
108
109
110
module Update.CloudUpdate
  ( cloudUpdate
  ) where

import List
import Random exposing (..)

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 -> Cloud -> Int -> (Cloud, Int, Seed)
cloudUpdate time boardSize seed player {points, spawn, lastSpawn} currentScore =
  let pointsToCatch = presentPoints time boardSize (points player.config)
      presentAndNotCaughtPoints = List.filter (not << (playerPointCollision time player)) pointsToCatch
      addScore = (List.length pointsToCatch) - (List.length presentAndNotCaughtPoints)
      presentOtherPoints = presentPoints time boardSize (points (otherConfig player.config))
      (newCloud, seed') =
        if time > lastSpawn + spawn then
          let (newPoint1, seed') = getNewPoint time boardSize seed currentScore
              (newPoint2, seed'') = getNewPoint time boardSize seed' currentScore
          in  ( { points = \config ->
                    if(config == player.config)
                      then
                        newPoint1 :: presentAndNotCaughtPoints
                      else
                        newPoint2 :: presentOtherPoints
                , spawn = spawn - sqrt(spawn) / 50
                , lastSpawn = time
                }
              , 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 time boardSize points =
  let isPresent point = (distance (pointMove point time) originVec) < (pointAwayDist boardSize)
  in  List.filter isPresent points

getNewPoint : Float -> Vec2 -> Seed -> Int -> (Point, Seed)
getNewPoint time boardSize seed currentScore =
  let (initPos, seed') = pointInitPos boardSize seed
      (initDest, seed'') = pointDestination boardSize seed'
  in  ( { initTime = time
        , initPos = initPos
        , initDest = initDest
        , move = \initTime initPos initDest time ->
            let delta = time - initTime
                move = (currentLevel currentScore).move initPos initDest delta
            in  initPos `add` move
        }
      , seed''
      )

pointInitPos : Vec2 -> Seed -> (Vec2, Seed)
pointInitPos boardSize seed =
  let (rand, seed') = generate floatGen seed
      angle = rand * (degrees 360)
      dist = pointSpawnDist boardSize
  in  (polarToCartesian angle dist, seed')

pointDestination : Vec2 -> Seed -> (Vec2, Seed)
pointDestination boardSize seed =
  case generateMany 4 floatGen seed of
    ([r1, r2, r3, r4], seed') ->
      ( randomBoardPosition boardSize (r1, r2) (r3, r4)
      , seed'
      )
    _ ->
      ( randomBoardPosition boardSize (0, 0) (0, 0)
      , seed
      )

generateMany : Int -> Generator a -> Seed -> (List a, Seed)
generateMany count gen seed =
  if count == 0
    then
      ([], seed)
    else
      let (rand, seed') = generate gen seed
          (randList, seed'') = generateMany (count - 1) gen seed'
      in  (rand :: randList, seed'')

floatGen : Generator Float
floatGen = float 0 1

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
      }