Commit c4ae3b0e authored by Joris Guyonvarch's avatar Joris Guyonvarch

Initial commit

parents
src/build
src/cache
<!DOCTYPE HTML>
<html>
<head>
<title>Avoid</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="resources/elm-runtime.js"></script>
<script src="src/build/Main.js"></script>
</head>
<body>
<h1>Avoid</h1>
<div id="game"></div>
<script type="text/javascript">
var myPorts = {};
var myContainer = document.getElementById('game');
var myModule = Elm.Main;
Elm.embed(myModule, myContainer, myPorts);
</script>
<a href="https://github.com/guyonvarch/avoid">
<img style="position: absolute; top: 0; right: 0; border: 0;"
src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67"
alt="Fork me on GitHub"
data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png">
</a>
</body>
</html>
This diff is collapsed.
module Board where
import Vec2 (Vec2)
boardSize : Vec2
boardSize =
{ x = 500
, y = 500
}
boardDiagonal : Float
boardDiagonal =
let x = boardSize.x
y = boardSize.y
in sqrt(x^2 + y^2)
module Display where
import Vec2 (..)
import Player (..)
import Game (Game)
import Enemy (..)
import Board (boardSize)
display : Game -> Element
display {time, player, enemyState, bestTime} =
let enemyForms = map (enemyForm time) enemyState.enemies
forms = boardForms
++ playerForms player
++ enemyForms
++ bestTimeForms bestTime
++ timeForms time
in collage (truncate boardSize.x) (truncate boardSize.y) forms
boardForms : [Form]
boardForms = [filled boardColor (rect boardSize.x boardSize.y)]
boardColor : Color
boardColor = rgb 34 122 34
playerForms : Player -> [Form]
playerForms player = [circleForm player.pos playerSize playerColor]
playerColor : Color
playerColor = rgb 224 224 224
enemyForm : Float -> Enemy -> Form
enemyForm time enemy =
let pos = enemyMove enemy time
in circleForm pos enemySize enemyColor
enemyColor : Color
enemyColor = rgb 170 0 0
circleForm : Vec2 -> Float -> Color -> Form
circleForm pos size color =
let outline = circle size
|> filled black
inside = circle (size - 2)
|> filled color
in group [outline, inside]
|> move (pos.x, pos.y)
bestTimeForms : Float -> [Form]
bestTimeForms bestTime =
if(bestTime > 0) then
let seconds = truncate (bestTime / 1000)
text = "Record: " ++ (show seconds)
pos =
{ x = boardSize.x / 2 - 65
, y = -boardSize.y / 2 + 30
}
in [textForm text pos rightAligned]
else []
timeForms : Float -> [Form]
timeForms time =
let seconds = truncate (time / 1000)
text = (show seconds)
pos = { x = 0.0, y = boardSize.y / 2 - 30 }
in [textForm text pos centered]
textForm : String -> Vec2 -> (Text -> Element) -> Form
textForm content pos alignment =
let textElement = toText content
|> typeface ["calibri", "arial"]
|> Text.color textColor
|> bold
|> alignment
in textElement
|> toForm
|> move (pos.x, pos.y)
textColor : Color
textColor = rgb 224 224 224
module Enemy where
import Vec2 (..)
import Board (boardDiagonal)
type Enemy =
{ 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
enemySize : Float
enemySize = 8
enemySpeed : Float -> Float
enemySpeed dt = dt / 25
enemySpawnDist : Float
enemySpawnDist = boardDiagonal * 3 / 5
enemyAwayDist : Float
enemyAwayDist = boardDiagonal
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
}
playerEnemyCollision : Float -> Player -> Enemy -> Bool
playerEnemyCollision time player enemy =
let enemyPos = enemyMove enemy time
in (distance enemyPos player.pos) < enemySize + playerSize
playerEnemiesCollision : Float -> Player -> [Enemy] -> Bool
playerEnemiesCollision time player enemies =
let collision = playerEnemyCollision time player
in length (filter collision enemies) > 0
module Game where
import Player (..)
import Enemy (..)
import EnemyState (..)
import Vec2 (Vec2)
type Game =
{ time : Float
, player : Player
, enemyState : EnemyState
, bestTime : Float
}
initialGame : Vec2 -> Float -> Game
initialGame playerPos bestTime =
let initPlayer =
{ pos = playerPos
, speed = { x = 0, y = 0 }
}
in { time = 0
, player = initPlayer
, enemyState = initEnemyState
, bestTime = bestTime
}
module Geometry where
import Vec2 (..)
import Board (boardSize)
polarToCartesian : Float -> Float -> Vec2
polarToCartesian angle dist =
{ x = dist * (cos angle)
, y = dist * (sin angle)
}
distance : Vec2 -> Vec2 -> Float
distance v1 v2 = sqrt((v2.x - v1.x)^2 + (v2.y - v1.y)^2)
inBoard : Float -> Vec2 -> Vec2
inBoard size pos =
let leftX = -boardSize.x / 2 + size
rightX = boardSize.x / 2 - size
bottomY = -boardSize.y / 2 + size
topY = boardSize.y / 2 - size
in { x = clamp leftX rightX pos.x
, y = clamp bottomY topY pos.y
}
module Input where
import Keyboard
import Random
import RandomValues (RandomValues)
import Vec2 (Vec2)
type Input =
{ dir : Vec2
, delta : Time
, randomValues : RandomValues
}
getInput : Signal Input
getInput =
let dtSignal = delta
dirSignal = lift recordIntToVec2 Keyboard.arrows
randomFloatsSignal = Random.floatList (lift (\_ -> 3) dtSignal)
randomValuesSignal = lift floatsToRandomValues randomFloatsSignal
in sampleOn dtSignal <| Input <~ dirSignal
~ dtSignal
~ randomValuesSignal
delta : Signal Time
delta = lift (\ms -> ms) (fps 25)
recordIntToVec2 : {x : Int, y : Int} -> Vec2
recordIntToVec2 {x, y} =
{ x = toFloat x
, y = toFloat y
}
floatsToRandomValues : [Float] -> RandomValues
floatsToRandomValues [enemyAngle, enemyX, enemyY] =
{ enemyAngle = enemyAngle
, enemyX = enemyX
, enemyY = enemyY
}
module Main where
import Game (initialGame)
import Display (display)
import Step (step)
import Input (getInput)
import Vec2 (originVec)
main : Signal Element
main = lift display (foldp step (initialGame originVec 0) getInput)
module Physics where
import Vec2 (..)
getNewPosAndSpeed : Float -> Vec2 -> (Float -> Float) -> (Vec2, Vec2) -> (Vec2, Vec2)
getNewPosAndSpeed dt dir computeSpeed (pos, speed) =
let move = getMove (computeSpeed dt) dir
acc = getAcc move speed
newPos = getNewPos dt acc speed pos
newSpeed = getNewSpeed dt acc speed
in ( newPos
, newSpeed
)
getMove : Float -> Vec2 -> Vec2
getMove speed dir =
if (isNull dir)
then {x = 0, y = 0}
else
let angle = atan2 dir.y dir.x
in { x = speed * cos angle
, y = speed * sin angle
}
getAcc : Vec2 -> Vec2 -> Vec2
getAcc move speed = (move `div` 800) `sub` (speed `div` 1000)
getNewPos : Float -> Vec2 -> Vec2 -> Vec2 -> Vec2
getNewPos dt acc speed pos =
((dt^2 / 2) `mul` acc) `add` ((dt `mul` speed) `add` pos)
getNewSpeed : Float -> Vec2 -> Vec2 -> Vec2
getNewSpeed dt acc speed = add (mul dt acc) speed
module Player where
import Vec2 (..)
type Player =
{ pos : Vec2
, speed : Vec2
}
playerSize : Float
playerSize = 10
playerSpeed : Float -> Float
playerSpeed dt = dt / 500
module RandomValues where
type RandomValues =
{ enemyAngle : Float
, enemyX : Float
, enemyY : Float
}
module Step where
import Vec2 (..)
import Game (..)
import Player (..)
import EnemyState (..)
import Player (playerSpeed)
import Enemy (enemySpeed, enemyMove, enemyAwayDist)
import Input (Input)
import Physics (getNewPosAndSpeed, getMove)
import Board (boardSize, boardDiagonal)
import Geometry (..)
import RandomValues (RandomValues)
step : Input -> Game -> Game
step {dir, delta, randomValues} {time, player, enemyState, bestTime} =
if(playerEnemiesCollision time player enemyState.enemies) then
let newBestTime = if(time > bestTime) then time else bestTime
in initialGame player.pos newBestTime
else
let newTime = time + delta
newPlayer = playerStep delta dir player
newEnemyState = enemyStep time randomValues enemyState
in { time = newTime
, player = newPlayer
, enemyState = newEnemyState
, bestTime = bestTime
}
playerStep : Float -> Vec2 -> Player -> Player
playerStep dt dir player =
let (pos, speed) = getNewPosAndSpeed dt dir playerSpeed (player.pos, player.speed)
in { pos = inBoard playerSize pos
, speed = speed
}
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 =
let destWidth = boardSize.x
destHeight = boardSize.y
in { x = destWidth * randomValues.enemyX - destWidth / 2
, y = destHeight * randomValues.enemyY - destHeight / 2
}
module Vec2 where
type Vec2 =
{ x : Float
, y : Float
}
add : Vec2 -> Vec2 -> Vec2
add v1 v2 =
{ x = v1.x + v2.x
, y = v1.y + v2.y
}
sub : Vec2 -> Vec2 -> Vec2
sub v1 v2 =
{ x = v1.x - v2.x
, y = v1.y - v2.y
}
mul : Float -> Vec2 -> Vec2
mul m v =
{ x = m * v.x
, y = m * v.y
}
div : Vec2 -> Float -> Vec2
div v d =
{ x = v.x / d
, y = v.y / d
}
isNull : Vec2 -> Bool
isNull v = (v.x == 0) && (v.y == 0)
originVec : Vec2
originVec = { x = 0, y = 0 }
elm --make --only-js Main.elm
body {
margin: 0;
background-color: #111111;
font-family: calibri;
}
h1 {
font-weight: bold;
background-color: #225522;
min-width: 500px;
color: #e0e0e0;
margin: 0;
padding-top: 20px;
padding-bottom: 20px;
text-align: center;
}
#game {
margin-left: auto;
margin-right: auto;
border-top: 10px dashed #222222;
border-bottom: 10px dashed #222222;
width: 500px;
height: 500px;
}
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