module Main exposing (main)
module Main exposing (main)
import Browser
import Browser.Events exposing (onAnimationFrame)
import Html exposing (Html)
import Html.Attributes as Attr
import Random
import Svg exposing (circle, g, svg)
import Svg.Attributes exposing (cx, cy, fill, height, opacity, r, transform, viewBox, width)
import Time
main : Program () Model Msg
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
type alias Model =
{ time : Float
, stars : List Star
}
type alias Star =
{ x : Float
, y : Float
, vx : Float
, vy : Float
, lifetime : Float
}
init : () -> ( Model, Cmd Msg )
init _ =
( { time = 0
, stars = []
}
, generateStar
)
type Msg
= Tick Float
| NewStar Star
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Tick delta ->
( { model
| time = model.time + delta
, stars = updateStars model.stars
}
, generateStar
)
NewStar star ->
( { model
| stars = star :: model.stars
}
, Cmd.none
)
updateStars : List Star -> List Star
updateStars stars =
stars
|> List.filter (\p -> p.lifetime > 0)
|> List.map updateStar
updateStar : Star -> Star
updateStar star =
{ star
| x = star.x + star.vx
, y = star.y + star.vy
, lifetime = star.lifetime - 5
}
generateStar : Cmd Msg
generateStar =
Random.generate NewStar starGenerator
starGenerator : Random.Generator Star
starGenerator =
Random.map5 Star
(Random.float -4 4)
(Random.float -4 4)
(Random.float -0.05 0.05)
(Random.float -0.05 0.05)
(Random.float 50 300)
subscriptions : Model -> Sub Msg
subscriptions _ =
onAnimationFrame (\time -> Tick (Time.posixToMillis time |> toFloat))
view : Model -> Html Msg
view model =
svg
[ width "100%"
, height "100%"
, viewBox "0 0 100 100"
]
[ g [ transform "translate(48, 32)" ]
[ circle
[ cx "0"
, cy "100"
, r "20"
, fill "black"
, opacity "0.9"
]
[]
, g [] (List.map viewStar model.stars)
]
]
viewStar : Star -> Svg.Svg msg
viewStar star =
circle
[ cx (String.fromFloat star.x)
, cy (String.fromFloat star.y)
, r "0.25"
, fill "white"
, opacity (String.fromFloat (star.lifetime / 100))
]
[]