Created
December 15, 2015 10:37
-
-
Save yonax/0beb5dc96e990dc87ffa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Graphics.Collage exposing (..) | |
import Graphics.Element exposing (..) | |
import Random | |
import Color exposing (Color) | |
import Time exposing (fps) | |
type alias Vector = (Float, Float) | |
type alias Circle = | |
{ center : Vector | |
, r : Float | |
, v : Vector | |
, color : Color | |
} | |
width = 800 | |
height = 800 | |
type alias Model = List Circle | |
randomVector : Float -> Float -> Random.Generator Vector | |
randomVector a b = Random.pair (Random.float a b) (Random.float a b) | |
randomColor : Random.Generator Color | |
randomColor = Random.map3 Color.rgb (Random.int 0 255) (Random.int 0 255) (Random.int 0 255) | |
randomCircle : Random.Generator Circle | |
randomCircle = Random.map4 Circle (randomVector (-width/2) (width/2)) (Random.float 30 150) (randomVector -3 3) randomColor | |
(.+) : Vector -> Vector -> Vector | |
(.+) (x, y) (x', y') = (x + x', y + y') | |
dist : Vector -> Vector -> Float | |
dist (x, y) (x', y') = sqrt ((x - x')*(x - x') + (y - y')*(y - y')) | |
mid : Vector -> Vector -> Vector | |
mid (x, y) (x', y') = ((x + x') / 2, (y + y') / 2) | |
neg : Vector -> Vector | |
neg (x, y) = (-x, -y) | |
type alias Overlap = | |
{ center : Vector, | |
r : Float, | |
color : Color | |
} | |
overlap : Circle -> Circle -> Maybe Overlap | |
overlap c c' = | |
let | |
amount = (dist (c.center) (c'.center)) - c.r - c'.r | |
interp c1 c2 = Color.rgb ((c1.red + c2.blue) // 2) ((c1.green + c2.red) // 2) ((c1.green + c2.green) // 2) | |
in | |
if amount >= 0 then | |
Nothing | |
else | |
Just { center=mid c.center c'.center | |
, r=amount | |
, color=interp (Color.toRgb c.color) (Color.toRgb c'.color) | |
} | |
initModel : Int -> Model | |
initModel n = Random.list n randomCircle |> flip Random.generate (Random.initialSeed 200) |> fst | |
fit : Vector -> Bool | |
fit (x, y) = x >= (-width/2) && x < (width/2) && y >= (-width / 2) && y < (width/2) | |
updateCircle c = | |
let | |
newCenter = c.center .+ c.v | |
in | |
{ c | center = newCenter | |
, v = if fit newCenter then c.v else neg c.v | |
} | |
update : Model -> Model | |
update = List.map updateCircle | |
model : Signal Model | |
model = Signal.foldp (\_ s -> update s) (initModel 30) (fps 30) | |
scene circles = | |
let | |
overlaps = List.concatMap (\c -> List.filterMap (overlap c) circles) circles | |
drawCircle {center, r, color} = circle (-r) |> outlined {defaultLine | color=color} |> move center | |
in | |
collage 800 800 <| (List.map drawCircle overlaps) | |
main = Signal.map scene model |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment