I’m too tired to write a proper blog post about this but I managed to port DonSyme’s Game of Life Demo that comes with the F# Distribution to Silverlight. It’s not a full port as there were some UI events that I couldn’t get to work for love nor money – I think these maybe bugs in Silverlight itself. However the game does look pretty cool. Also Silverlight currently has no way to marshal back to the UI thread which makes multithreading a bit difficult.
The game was relatively simple to port, in fact I kept the first few files, “alg.fsi”, “alg.fs” and “worker.fs” in tacked and just replaced the client.fs with the following:
#light
namespace SilverLife
open System;
open System.Collections.Generic;
open System.Windows.Browser;
open System.Threading;
open System.Windows
open System.Windows.Controls
open System.Windows.Documents
open System.Windows.Ink
open System.Windows.Input
open System.Windows.Media
open System.Windows.Media.Animation
open System.Windows.Shapes
type Page() = class
inherit Canvas() as base
member x.Page_Loaded(o : obj, e : EventArgs) =
let canvas = o :?> Canvas
let gridSize = 23
/// Create and configure the worker automata, ready to be placed
/// onto a thread.
let rec worker = Worker.mkWorker gridSize
and grid =
[| for x in 0 .. gridSize ->
[| for y in 0 .. gridSize ->
let image = new Image()
image.Source <- new Uri("RedBloodcellOff.jpg", UriKind.Relative)
image.SetValue(Canvas.TopProperty, y * 14)
image.SetValue(Canvas.LeftProperty, x * 14)
canvas.Children.Add(image)
image |] |]
and bornQueue = new Queue<Game.points>()
and diedQueue = new Queue<Game.points>()
// This is the refresh operation that will be invoked by the worker.
and workerNotifyUpdates (born,died) =
lock bornQueue (fun () -> bornQueue.Enqueue(born))
lock diedQueue (fun () -> diedQueue.Enqueue(died))
and workerThread = new Thread(start=(fun () -> worker.Start()), IsBackground = true, Priority = ThreadPriority.Lowest)
worker.Updates.Add(workerNotifyUpdates)
let dequeueAll (queue : Queue<Game.points>) image =
while (queue.Count > 0) do
let points = queue.Dequeue()
List.iter (fun (x,y) -> grid.[x].[y].Source <- new Uri(image, UriKind.Relative) ) points
let timer_Tick _ =
lock bornQueue (fun () -> dequeueAll bornQueue "RedBloodcellOn.jpg")
lock diedQueue (fun () -> dequeueAll diedQueue "RedBloodcellOff.jpg")
let timer = new HtmlTimer()
timer.Interval <- 1
timer.Tick.Add(timer_Tick)
timer.Enabled <- true
workerThread.Start()
()
member x.ClickSquare(sender : obj, e : MouseEventArgs) = ()
end
You can see the game at the following URL (careful I’ve noticed it crashes the browser sometimes, I guess that’s what they mean by “alpha”):
http://www.strangelights.com/fsharp/silverlight/life.aspx
Of course you need the silverlight 1.1 alpha installed here’s a screen shot for those that don’t have that.
