Skip to content

Instantly share code, notes, and snippets.

@samm81
Created September 3, 2017 23:12
Show Gist options
  • Save samm81/a4da5d7b52f2e2254c05b780667294dc to your computer and use it in GitHub Desktop.
Save samm81/a4da5d7b52f2e2254c05b780667294dc to your computer and use it in GitHub Desktop.
an old abandoned elm project where emoji run around on the page
module Main exposing (..)
import Html exposing (Html)
import Html.App as Html
import Html.Attributes exposing (style)
import Time exposing (fps, every, second)
import Signal exposing (Signal)
import Random exposing (Generator, Seed, initialSeed, int, float, generate)
import List exposing (head, tail)
import Graphics.Element exposing (Element, show)
import Graphics.Collage exposing (move, text, toForm, collage, scale, filled, ngon, circle)
import Color exposing (red, blue, green)
import Text exposing (fromString)
import Window
import Mouse
import AnimationFrame
import Anmation exposing (..)
import Debug exposing (..)
type alias Model =
{ time: Float
, emojis: List Emoji
, seed: Random.Seed
, dim: { x: Int, y: Int }
, mouse: { x: Int, y: Int }
}
type Msg = Frame
| Tick Float
| Newmoji
| MouseMove (Int, Int)
| Resize (Int, Int)
| NoOp
type alias Emoji =
(String, (Float, Float), (Float, Float), (Float, Float), (Float, Float))
-- emoji, x, y, xdot, ydot, f_x, f_y, targetx,targety
initialModel : Model
initialModel =
{ time = 0
, emojis = []
, seed = initialSeed 42
, dim = { x = 900, y = 900 }
, mouse = { x = 0, y = 0 }
}
view : Model -> Html Msg
view model =
(fromString "🔥"
|> text
|> scale 2)
::
(model.emojis
|> List.map (\(str, (x, y), (xdot, ydot), (fx, fy), (tx, ty)) ->
fromString str
|> text
|> move (x, y)
|> scale 2
))
|> collage model.dim.x model.dim.y
physics : List Emoji -> List Emoji
physics emojis =
let friction = 0.98
in emojis
|> List.map (\(str, (x, y), (xdot, ydot), (fx, fy), (tx, ty)) ->
(str,
(x + xdot, y + ydot),
(xdot + (fx * friction), ydot + (fy * friction)),
(fx, fy),
(tx, ty)
)
)
think : Model -> Model
think model =
let updated_emojis = model.emojis
|> List.map (\(str, (x, y), (xdot, ydot), (fx, fy), (tx, ty)) ->
(str,
(x, y),
(xdot, ydot),
(pid (x, y) (xdot, ydot) (tx, ty) (0.001, 0.05)),
(tx, ty)
)
)
in { model | emojis = updated_emojis }
pid : (Float, Float) -> (Float, Float) -> (Float, Float) -> (Float, Float) -> (Float, Float)
pid (x, y) (xdot, ydot) (tx, ty) (p, d) =
let xerr = (tx - x)
yerr = (ty - y)
in ( (xerr * p) - (xdot * d), (yerr * p) - (ydot * d) )
update : Msg -> Model -> Model
update action model =
case action of
Frame -> { model | emojis = (physics model.emojis) }
Tick time ->
let modelprime = think model
in { modelprime | time = time }
Newmoji ->
let (new_emoji, seed) = (generate_emoji model)
in { model | emojis = new_emoji :: model.emojis, seed = seed }
MouseMove (x, y) ->
let xprime = x - model.dim.x // 2
yprime = -y + model.dim.y // 2
in { model | mouse = { x = xprime, y = yprime } }
Resize (x, y) -> { model | dim = { x = x, y = y } }
NoOp -> model
actionSignal : Signal.Signal Msg
actionSignal = Signal.mergeMany
[ Signal.map (\_ -> Newmoji) (every (second / 4))
, Signal.map (\pos -> MouseMove pos) Mouse.position
, Signal.map (\_ -> Frame) (fps 35)
, Signal.map (\time -> Tick time) (fps 10)
, Signal.map (\dim -> Resize dim) Window.dimensions
]
modelSignal: Signal.Signal Model
modelSignal =
Signal.foldp update initialModel actionSignal
generate_emoji: Model -> (Emoji, Seed)
generate_emoji model =
let strgen : Generator String
strgen = Random.map (nemoji ["😶", "😃", "😝", "😭", "😮"]) (int 0 4)
posgen : Generator (Float, Float)
posgen = Random.pair
(float (toFloat (-model.dim.x // 2)) (toFloat (model.dim.x // 2)))
(float (toFloat (-model.dim.y // 2)) (toFloat (model.dim.y // 2)))
(str, seed) = Random.generate strgen model.seed
(pos, _) = Random.generate posgen model.seed
target = (fromPolar (80, (snd (toPolar pos))))
emoji = (str, pos, (0, 0), (0, 0), target)
in (emoji, seed)
nemoji: List String -> Int -> String
nemoji emojis n =
case emojis of
[] -> "uh oh"
hd::[] -> hd
hd::tl -> if n == 0 then hd else nemoji tl (n - 1)
subs: Sub Msg
subs =
Sub.batch
[ Window.resizes Resize
, AnimationFrame.diffs Tick
, Mouse.clicks Click
]
main : Signal.Signal Element
main =
Html.program
{ init = ( initialModel, Task.perform (always NoOp) Resize Window.size )
, update = (\msg model -> ( update msg model, Cmd.none ))
, subscriptions = always subs
, view = scene >> Element.toHtml
}
--Signal.map view modelSignal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment