Skip to content

Instantly share code, notes, and snippets.

@TheSeamau5
Last active August 29, 2015 14:25
Show Gist options
  • Save TheSeamau5/555ebbbf16a61b01cb4e to your computer and use it in GitHub Desktop.
Save TheSeamau5/555ebbbf16a61b01cb4e to your computer and use it in GitHub Desktop.
import Graphics.Element exposing (Element)
import Graphics.Collage exposing (..)
import Color
import Signal
import Time
-- Play with this value and hot swap the code
gravity = -9.8
--
type alias Body a =
{ position : a
, velocity : a
, mass : Float
, force : a
}
type alias Spring a =
{ stiffness : Float
, damping : Float
, position : a
}
applyForce : Float -> Body Float -> Body Float
applyForce force body =
{ body | force <- force + body.force }
attach : Spring Float -> Body Float -> Body Float
attach spring body =
let
springForce =
-spring.stiffness * (body.position - spring.position)
dampingForce =
-spring.damping * body.velocity
force =
(springForce + dampingForce) / 1000
in
applyForce force body
epsilon = 0.0001
animate : Float -> Body Float -> Body Float
animate dt body =
let
deltaTime =
dt / 1000
force =
body.force * 1000
acceleration =
force / body.mass
velocity =
body.velocity + deltaTime * acceleration
position =
body.position + deltaTime * body.velocity
in
{ body | position <- position
, velocity <- velocity
, force <- 0
}
-----------------
type alias State =
{ spring : Spring Float
, body : Body Float
}
initial : State
initial =
let
spring =
{ stiffness = 170
, damping = 10
, position = 0
}
body =
{ position = 100
, mass = 10
, velocity = 0
, force = 0
}
in
{ spring = spring
, body = body
}
type Action
= NextFrame Float
update : Action -> State -> State
update action state =
case action of
NextFrame frame ->
let
body =
state.body
|> applyForce gravity
|> attach state.spring
|> animate frame
in
{ state | body <- body }
view : State -> Element
view state =
let
forms =
let
spring =
rect 20 10
|> filled Color.gray
|> move (0, state.spring.position)
body =
circle 10
|> filled Color.red
|> move (0, state.body.position)
cord =
segment (0, state.spring.position) (0, state.body.position)
|> traced (solid Color.black)
in
[ spring, cord, body ]
in
collage 400 400 forms
actions =
Signal.map NextFrame (Time.fps 60)
main =
Signal.map view
(Signal.foldp update initial actions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment