module Update.CloudUpdate ( cloudUpdate ) where import List import Random (..) import Model.Vec2 (..) import Model.Player (..) import Model.Board (boardDiagonal) import Model.Point (..) import Model.Cloud (..) import Model.Config (..) import Utils.Geometry (..) import Utils.Physics (getMove, getWaveMove) cloudUpdate : Float -> Vec2 -> Seed -> Player -> Cloud -> (Cloud, Int, Seed) cloudUpdate time boardSize seed player {points, spawn, lastSpawn} = 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 (newPoint2, seed'') = getNewPoint time boardSize seed' 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 -> (Point, Seed) getNewPoint time boardSize seed = 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 = getMove (pointSpeed delta) (initDest `sub` initPos) in initPos `add` move } , seed'' ) pointInitPos : Vec2 -> Seed -> (Vec2, Seed) pointInitPos boardSize seed = let (rand, seed') = generate floatGen seed angle = rand * (degrees 360) dist = (boardDiagonal boardSize) * 3 / 5 in (polarToCartesian angle dist, seed') pointDestination : Vec2 -> Seed -> (Vec2, Seed) pointDestination boardSize seed = let ([r1, r2, r3, r4], seed') = generateMany 4 floatGen seed in ( randomBoardPosition boardSize (r1, r2) (r3, r4) , 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 }