Commit 4521cdf1 authored by Joris Guyonvarch's avatar Joris Guyonvarch

Adding multiple moving points to catch

parent c2583cf7
Avoid
=====
Avoid red enemies and catch the most green targets as possible.
Avoid red points and catch the most green points as possible.
You can play at [http://guyonvarch.github.io/avoid](http://guyonvarch.github.io/avoid).
module Cloud where
import Point (..)
import Player (..)
import Geometry (distance)
type Cloud =
{ greenPoints : [Point]
, redPoints : [Point]
, spawn : Float
, lastSpawn : Float
}
initCloud : Cloud
initCloud =
let spawn = 200
in { greenPoints = []
, redPoints = []
, spawn = spawn
, lastSpawn = -spawn
}
playerPointsCollision : Float -> Player -> [Point] -> Bool
playerPointsCollision time player points =
let collision = playerPointCollision time player
in length (filter collision points) > 0
playerPointCollision : Float -> Player -> Point -> Bool
playerPointCollision time player point =
let pointPos = pointMove point time
in (distance pointPos player.pos) < pointSize + playerSize
module CloudStep where
import Vec2 (..)
import Geometry (..)
import Player (..)
import Board (boardSize, boardDiagonal)
import Point (..)
import RandomValues (..)
import Physics (getMove)
import Cloud (..)
cloudStep : Float -> RandomValues -> Player -> Cloud -> (Cloud, Int)
cloudStep time {greenPoint, redPoint} player {greenPoints, redPoints, spawn, lastSpawn} =
let insideGreenPoints = presentPoints time greenPoints
insideNotCaughtGreenPoints = filter (not . (playerPointCollision time player)) insideGreenPoints
addScore = (length insideGreenPoints) - (length insideNotCaughtGreenPoints)
presentRedPoints = presentPoints time redPoints
newCloud =
if time > lastSpawn + spawn then
let newGreenPoint = newPoint time greenPoint
newRedPoint = newPoint time redPoint
in
{ greenPoints = newGreenPoint :: insideNotCaughtGreenPoints
, redPoints = newRedPoint :: presentRedPoints
, spawn = spawn - sqrt(spawn) / 50
, lastSpawn = time
}
else
{ greenPoints = insideNotCaughtGreenPoints
, redPoints = presentRedPoints
, spawn = spawn
, lastSpawn = lastSpawn
}
in (newCloud, addScore)
presentPoints : Float -> [Point] -> [Point]
presentPoints time points =
let isPresent point = (distance (pointMove point time) originVec) < pointAwayDist
in filter isPresent points
newPoint : Float -> PointRandomValues -> Point
newPoint time pointRandomValues =
{ initTime = time
, initPos = pointInitPos pointRandomValues.angle
, initDest = pointDestination pointRandomValues.x pointRandomValues.y
, move initTime initPos initDest time =
let delta = time - initTime
move = getMove (pointSpeed delta) (initDest `sub` initPos)
in initPos `add` move
}
pointInitPos : Float -> Vec2
pointInitPos randomAngle =
let angle = randomAngle * (degrees 360)
dist = boardDiagonal * 3 / 5
in polarToCartesian angle dist
pointDestination : Float -> Float -> Vec2
pointDestination randomX randomY =
randomBoardPosition (randomX, randomY) (1, 1)
randomBoardPosition : (Float, Float) -> (Float, Float) -> Vec2
randomBoardPosition (randomX, randomY) (percentX, percentY) =
let width = boardSize.x * percentX
height = boardSize.y * percentY
in { x = width * randomX - width / 2
, y = height * randomY - height / 2
}
......@@ -3,18 +3,18 @@ module Display where
import Vec2 (..)
import Player (..)
import Game (Game)
import Enemy (..)
import Point (..)
import Board (boardSize)
import Target (..)
display : Game -> Element
display {time, player, target, enemyState, bestScore} =
let enemyForms = map (enemyForm time) enemyState.enemies
display {time, score, player, cloud, bestScore} =
let greenPointForms = map (pointForm time greenPointColor) cloud.greenPoints
redPointForms = map (pointForm time redPointColor) cloud.redPoints
forms = boardForms
++ playerForms player
++ targetForms target.pos
++ enemyForms
++ scoreForms target.score
++ greenPointForms
++ redPointForms
++ scoreForms score
++ bestScoreForms bestScore
in collage (truncate boardSize.x) (truncate boardSize.y) forms
......@@ -30,19 +30,16 @@ playerForms player = [circleForm player.pos playerSize playerColor]
playerColor : Color
playerColor = rgb 224 224 224
targetForms : Vec2 -> [Form]
targetForms pos = [circleForm pos targetSize targetColor]
pointForm : Float -> Color -> Point -> Form
pointForm time color point =
let pos = pointMove point time
in circleForm pos pointSize color
targetColor : Color
targetColor = rgb 34 85 34
greenPointColor : Color
greenPointColor = rgb 34 85 34
enemyForm : Float -> Enemy -> Form
enemyForm time enemy =
let pos = enemyMove enemy time
in circleForm pos enemySize enemyColor
enemyColor : Color
enemyColor = rgb 170 0 0
redPointColor : Color
redPointColor = rgb 170 0 0
circleForm : Vec2 -> Float -> Color -> Form
circleForm pos size color =
......
module EnemyState where
import Enemy (..)
import Player (..)
import Geometry (distance)
type EnemyState =
{ enemies : [Enemy]
, spawn : Float
, lastSpawn : Float
}
initEnemyState : EnemyState
initEnemyState =
let spawn = 200
in { enemies = []
, spawn = spawn
, lastSpawn = -spawn
}
playerEnemiesCollision : Float -> Player -> [Enemy] -> Bool
playerEnemiesCollision time player enemies =
let collision = playerEnemyCollision time player
in length (filter collision enemies) > 0
playerEnemyCollision : Float -> Player -> Enemy -> Bool
playerEnemyCollision time player enemy =
let enemyPos = enemyMove enemy time
in (distance enemyPos player.pos) < enemySize + playerSize
module Game where
import Player (..)
import Enemy (..)
import EnemyState (..)
import Target(..)
import Cloud (..)
import Vec2 (Vec2)
type Game =
{ time : Float
, score : Int
, player : Player
, target : Target
, enemyState : EnemyState
, cloud : Cloud
, bestScore : Int
}
......@@ -22,8 +20,8 @@ initialGame playerPos bestScore =
}
in
{ time = 0
, score = 0
, player = initPlayer
, target = initTarget
, enemyState = initEnemyState
, cloud = initCloud
, bestScore = bestScore
}
......@@ -16,7 +16,7 @@ getInput : Signal Input
getInput =
let dtSignal = delta
dirSignal = lift recordIntToVec2 Keyboard.arrows
randomFloatsSignal = Random.floatList (lift (\_ -> 5) dtSignal)
randomFloatsSignal = Random.floatList (lift (\_ -> 6) dtSignal)
randomValuesSignal = lift floatsToRandomValues randomFloatsSignal
in sampleOn dtSignal <| Input <~ dirSignal
~ dtSignal
......@@ -32,10 +32,17 @@ recordIntToVec2 {x, y} =
}
floatsToRandomValues : [Float] -> RandomValues
floatsToRandomValues [enemyAngle, enemyX, enemyY, targetX, targetY] =
{ enemyAngle = enemyAngle
, enemyX = enemyX
, enemyY = enemyY
, targetX = targetX
, targetY = targetY
}
floatsToRandomValues [angle1, x1, y1, angle2, x2, y2] =
let greenPoint =
{ angle = angle1
, x = x1
, y = y1
}
redPoint =
{ angle = angle2
, x = x2
, y = y2
}
in { greenPoint = greenPoint
, redPoint = redPoint
}
......@@ -7,4 +7,4 @@ import Input (getInput)
import Vec2 (originVec)
main : Signal Element
main = lift display (foldp step (initialGame { x = -50, y = 0 } 0) getInput)
main = lift display (foldp step (initialGame originVec 0) getInput)
module Enemy where
module Point where
import Vec2 (..)
import Board (boardDiagonal)
type Enemy =
type Point =
{ initTime : Float
, initPos : Vec2
, initDest : Vec2
, move : Float -> Vec2 -> Vec2 -> Float -> Vec2
}
enemyMove : Enemy -> Float -> Vec2
enemyMove enemy time =
enemy.move enemy.initTime enemy.initPos enemy.initDest time
pointMove : Point -> Float -> Vec2
pointMove {initTime, initPos, initDest, move} time =
move initTime initPos initDest time
enemySize : Float
enemySize = 5
pointSize : Float
pointSize = 5
enemySpeed : Float -> Float
enemySpeed dt = dt / 25
pointSpeed : Float -> Float
pointSpeed dt = dt / 25
enemySpawnDist : Float
enemySpawnDist = boardDiagonal * 3 / 5
pointSpawnDist : Float
pointSpawnDist = boardDiagonal * 3 / 5
enemyAwayDist : Float
enemyAwayDist = boardDiagonal
pointAwayDist : Float
pointAwayDist = boardDiagonal * 3 / 4
module RandomValues where
type RandomValues =
{ enemyAngle : Float
, enemyX : Float
, enemyY : Float
, targetX : Float
, targetY : Float
{ greenPoint : PointRandomValues
, redPoint : PointRandomValues
}
type PointRandomValues =
{ angle : Float
, x : Float
, y : Float
}
......@@ -3,30 +3,28 @@ module Step where
import Vec2 (..)
import Game (..)
import Player (..)
import EnemyState (..)
import Cloud (..)
import Geometry (..)
import Player (playerSpeed)
import Enemy (enemySpeed, enemyMove, enemyAwayDist)
import Point (pointSpeed, pointMove, pointAwayDist)
import Input (Input)
import Physics (getNewPosAndSpeed, getMove)
import Board (boardSize, boardDiagonal)
import Geometry (..)
import RandomValues (RandomValues)
import Target(..)
import Physics (getNewPosAndSpeed)
import RandomValues (..)
import CloudStep (cloudStep)
step : Input -> Game -> Game
step {dir, delta, randomValues} {time, player, target, enemyState, bestScore} =
if(playerEnemiesCollision time player enemyState.enemies) then
let newBestScore = if(target.score > bestScore) then target.score else bestScore
step {dir, delta, randomValues} {time, score, player, cloud, bestScore} =
if(playerPointsCollision time player cloud.redPoints) then
let newBestScore = if(score > bestScore) then score else bestScore
in initialGame player.pos newBestScore
else
let newTime = time + delta
newPlayer = playerStep delta dir player
newTarget = targetStep player randomValues target
newEnemyState = enemyStep time randomValues enemyState
(newCloud, addScore) = cloudStep time randomValues player cloud
in { time = newTime
, score = score + addScore
, player = newPlayer
, target = newTarget
, enemyState = newEnemyState
, cloud = newCloud
, bestScore = bestScore
}
......@@ -36,53 +34,3 @@ playerStep dt dir player =
in { pos = inBoard playerSize pos
, speed = speed
}
targetStep : Player -> RandomValues -> Target -> Target
targetStep player randomValues target =
if(targetCollision player target) then
{ score = target.score + 1
, pos = randomBoardPosition (randomValues.targetX, randomValues.targetY) (0.8, 0.8)
}
else
target
enemyStep : Float -> RandomValues -> EnemyState -> EnemyState
enemyStep time randomValues {enemies, spawn, lastSpawn} =
let isPresent enemy = (distance (enemyMove enemy time) originVec) < enemyAwayDist
presentEnemies = filter isPresent enemies
in if time > lastSpawn + spawn then
let newEnemy =
{ initTime = time
, initPos = enemyInitPos randomValues
, initDest = enemyDestination randomValues
, move initTime initPos initDest time =
let delta = time - initTime
move = getMove (enemySpeed delta) (initDest `sub` initPos)
in initPos `add` move
}
in { enemies = newEnemy :: presentEnemies
, spawn = spawn - sqrt(spawn) / 50
, lastSpawn = time
}
else { enemies = presentEnemies
, spawn = spawn
, lastSpawn = lastSpawn
}
enemyInitPos : RandomValues -> Vec2
enemyInitPos randomValues =
let angle = randomValues.enemyAngle * (degrees 360)
dist = boardDiagonal * 3 / 5
in polarToCartesian angle dist
enemyDestination : RandomValues -> Vec2
enemyDestination randomValues =
randomBoardPosition (randomValues.enemyX, randomValues.enemyY) (1, 1)
randomBoardPosition : (Float, Float) -> (Float, Float) -> Vec2
randomBoardPosition (randomX, randomY) (percentX, percentY) =
let width = boardSize.x * percentX
height = boardSize.y * percentY
in { x = width * randomX - width / 2
, y = height * randomY - height / 2
}
module Target where
import Board (boardSize)
import Geometry (distance)
import Vec2 (Vec2)
import Player (..)
type Target =
{ score : Int
, pos : Vec2
}
targetSize : Float
targetSize = 20
targetCollision : Player -> Target -> Bool
targetCollision player target =
(distance player.pos target.pos) < playerSize + targetSize
initTarget : Target
initTarget =
{ score = 0
, pos = { x = 50, y = 0 }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment