Advertisement
Guest User

Untitled

a guest
Aug 27th, 2015
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.64 KB | None | 0 0
  1. namespace skarpt_blask
  2.  
  3. open System
  4. open Foundation
  5. open AppKit
  6. open CoreGraphics
  7.  
  8. module Animation =
  9.  
  10.     type Flake = {
  11.                     x: float
  12.                     y: float
  13.                     dx: float
  14.                     dy: float
  15.                     size: float
  16.                   }
  17.  
  18.     type State = {flakes: Flake list; repeller: (float*float) option}
  19.  
  20.     type Message =
  21.         | State of AsyncReplyChannel<State>
  22.         | Update of (State -> State)
  23.         | Repeller of float*float
  24.  
  25.     let create () =
  26.  
  27.         MailboxProcessor<Message>.Start(fun mailbox ->
  28.  
  29.             let spawn =
  30.                 let rnd = new System.Random ()
  31.                 fun () ->
  32.                     {   x = rnd.NextDouble() * Config.width
  33.                         y = Config.height * rnd.NextDouble()
  34.                         dx = (rnd.NextDouble() / 4.0) - 0.25
  35.                         dy = -0.3 - (rnd.NextDouble() / 2.0)
  36.                         size = rnd.NextDouble() * 8.0 + 5.0}
  37.  
  38.             let respawn () = {spawn () with y = Config.height + 10.0}
  39.  
  40.             let rec animate () = async {
  41.  
  42.                 do! Async.Sleep 10
  43.  
  44.                 Update (fun state ->
  45.                     let move flake =
  46.                         { flake with
  47.                             x = flake.x + flake.dx * Config.speed
  48.                             y = flake.y + flake.dy * Config.speed
  49.                         }
  50.                     let repell repeller flake =
  51.                         flake
  52.  
  53.                     let check (flake: Flake) =
  54.                         if flake.y < -flake.size ||
  55.                            flake.x < -flake.size ||
  56.                            flake.x > Config.width then respawn ()
  57.                         else flake
  58.  
  59.                     {state with flakes = state.flakes |> List.map (move >> (repell state.repeller) check) }
  60.  
  61.  
  62.                 ) |> mailbox.Post
  63.  
  64.                 do! animate ()
  65.             }
  66.  
  67.             let rec engine state =
  68.                 async {
  69.  
  70.                     let! incoming = mailbox.Receive ()
  71.  
  72.                     match incoming with
  73.                     | State reply ->
  74.                         reply.Reply state
  75.                         do! state |> engine
  76.                     | Update fn ->
  77.                         do! state |> fn |> engine
  78.                     | Repeller (x,y) ->
  79.                         do! {state with repeller = Some (x,y)} |> engine
  80.                 }
  81.             animate () |> Async.Start
  82.             {   flakes = List.init Config.flakes (fun _ -> spawn())
  83.                 repeller = Some (Config.width/2.0,Config.height/2.0)}
  84.             |> engine
  85.         )
  86.  
  87.  
  88.  
  89.  
  90. type SnowyView () as this =
  91.     inherit NSView ()
  92.  
  93.     do
  94.         this.Frame <- new CGRect(0.0,0.0,Config.width, Config.height)
  95.  
  96.     let animation = Animation.create ()
  97.  
  98.     let drawFlake (context: NSGraphicsContext) (flake: Animation.Flake) =
  99.         Config.snowColor.SetFill ()
  100.         let rect = new CGRect(flake.x,flake.y,flake.size,flake.size)
  101.         context.GraphicsPort.FillEllipseInRect rect
  102.  
  103.  
  104.     let drawBackground (context: NSGraphicsContext) =
  105.         Config.backgroundColor.SetFill ()
  106.         context.GraphicsPort.FillRect this.Frame
  107.  
  108.     override this.DrawRect dirty =
  109.         base.DrawRect dirty
  110.         let context = NSGraphicsContext.CurrentContext
  111.         drawBackground context
  112.         let state = animation.PostAndReply Animation.State
  113.         state.flakes |> List.iter (drawFlake context);
  114.  
  115.         async {
  116.             do! Async.Sleep 20 // ~ 50 FPS
  117.             this.InvokeOnMainThread (fun () -> this.SetNeedsDisplayInRect this.Frame)
  118.         } |> Async.Start
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement