Last active
March 15, 2016 05:15
-
-
Save andrelevi/51e827126f93fb51dc4e to your computer and use it in GitHub Desktop.
Simple particle system written in Elm. Must edit Graphics.Collage source to expose sprite function.
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 List exposing (map, head, concatMap, concat, append) | |
import Color exposing (..) | |
import Graphics.Collage exposing (..) | |
import Graphics.Element exposing (..) | |
import Mouse | |
import Window | |
import Random exposing (generate, list, float) | |
import Debug | |
import AnimationFrame | |
-- HELPERS | |
zip4 : List a -> List b -> List c -> List d -> List (a,b,c,d) | |
zip4 ws xs ys zs = | |
case (ws, xs, ys, zs) of | |
( w :: ws', x :: xs', y :: ys', z :: zs' ) -> | |
(w,x,y,z) :: zip4 ws' xs' ys' zs' | |
(_, _, _, _) -> | |
[] | |
-- CONSTANTS | |
particleCount = 15 | |
xBounds = 200 | |
yBounds = 200 | |
spritesheet = "imgs/sprites/particle_o_2x.png" | |
frameCount = 11 | |
maxFrame = frameCount - 1 | |
-- MODEL | |
type alias Particle = | |
{ x: Float | |
, y: Float | |
, speed: Float -- responsbile for velocity and frame change frequency | |
, frame: Float | |
} | |
xs = generate (list particleCount (float -xBounds xBounds)) <| Random.initialSeed 0 | |
ys = generate (list particleCount (float -yBounds yBounds)) <| (snd xs) | |
speeds = generate (list particleCount (float 0 2)) <| (snd ys) | |
framePointers = generate (list particleCount (float 0 maxFrame)) <| (snd speeds) | |
zippedProperties = zip4 (fst xs) (fst ys) (fst speeds) (fst framePointers) | |
particles : List Particle | |
particles = map (\(x, y, speed, frame) -> { x = x, y = y, speed = speed, frame = frame}) zippedProperties | |
-- UPDATE | |
update : (Int, Int) -> List Particle -> List Particle | |
update mousePosition particles = | |
map (\p -> step p mousePosition) particles | |
step : Particle -> (Int, Int) -> Particle | |
step p (mouseX, mouseY) = | |
let | |
velocityX = p.speed + ((toFloat mouseX) / 300) | |
velocityY = p.speed + ((toFloat mouseY) / 300) | |
newX = p.x + velocityX | |
newY = p.y + velocityY | |
newFrame = if p.frame + p.speed > maxFrame then 0 else p.frame + (p.speed / 40) | |
in | |
{ p | | |
x <- if newX > xBounds then -xBounds else newX, | |
y <- if newY > yBounds then -yBounds else newY, | |
frame <-newFrame | |
} | |
-- VIEW | |
showParticle : Particle -> Form | |
showParticle p = | |
sprite 40 40 ((floor p.frame) * 40, 0) spritesheet | |
|> move (p.x, p.y) | |
view : (Int, Int) -> List Particle -> Element | |
view (w, h) particles = | |
collage w h <| map showParticle particles | |
-- SIGNALS | |
main : Signal Element | |
main = | |
Signal.map2 view Window.dimensions (Signal.foldp update particles input) | |
input : Signal (Int, Int) | |
input = | |
Signal.sampleOn AnimationFrame.frame Mouse.position |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment