A quick search for “F# Mandelbrot” gave an article written by Luke Hoban back in 2007, that draws a Fractal to the console.
Time for a makeover with a sprinkling of Active patterns, Reactive programming, Parallel execution and Silverlight.
Simply draw a rectangle onto the Fractal to zoom in:
“Complex” maths using F# PowerPack library and an Active Pattern:
open Microsoft.FSharp.Math
let maxIteration = 255
let modSquared (c : Complex) =
c.RealPart * c.RealPart + c.ImaginaryPart * c.ImaginaryPart
let (|Escaped|DidNotEscape|) c =
let rec compute z iterations =
if(modSquared z >= 4.0)
then Escaped iterations
elif iterations = maxIteration
then DidNotEscape
else compute ((z * z) + c) (iterations + 1)
compute c 0
Tomas Petricek’s original Reactive Rectangles sample to select the zoom area:
let rec waiting() = async {
let! md = Async.AwaitObservable(main.MouseLeftButtonDown)
let rc = new Canvas(Background = transparentGray)
main.Children.Add(rc)
do! drawing(rc, md.GetPosition(main)) }
and drawing(rc:Canvas, pos) = async {
let! evt = Async.AwaitObservable(main.MouseLeftButtonUp, main.MouseMove)
match evt with
| Choice1Of2(up) ->
rc.Background <- SolidColorBrush(colorSelect.CurrentColor)
do! waiting()
| Choice2Of2(move) ->
moveControl rc pos (move.GetPosition(main))
do! drawing(rc, pos) }
do waiting() |> Async.StartImmediate
Parallel rendering over up to 4 cores using Async workflows:
do! [0..3]
|> List.map (fun y -> async {
render points (y,(height/4),4) buffer
})
|> Async.Parallel
Resources:
Source: FractalZoom.zip (3.89 kb)
Back in February Jon Harrop published an implementation of John Conway’s Game of Life in 32 lines of F# using WPF. I’ve managed to increase Jon’s example to a massive 50 lines but at the same time get it running in Silverlight. If you have Silverlight 4 installed you can click in the box below to kick start life.
Jon’s original code for calculating life:
module Game =
let count (a: _ [,]) x y =
let m, n = a.GetLength 0, a.GetLength 1
let mutable c = 0
for x in x-1..x+1 do
for y in y-1..y+1 do
if x>=0 && x<m && y>=0 && y<n && a.[x, y] then
c <- c + 1
if a.[x, y] then c-1 else c
let rule (a: _ [,]) x y =
match a.[x, y], count a x y with
| true, (2 | 3) | false, 3 -> true
| _ -> false
The Silverlight Control, containing a WriteableBitmap updated from an F# Async Workflow:
type GameControl(n) as control =
inherit System.Windows.Controls.UserControl()
let game =
let rand = System.Random()
Array2D.init n n (fun _ _ -> rand.Next 2 = 0) |> ref
let update _ = Game.rule !game |> Array2D.init n n
let bitmap = System.Windows.Media.Imaging.WriteableBitmap(n,n)
do control.Content <- System.Windows.Controls.Image(Source=bitmap)
let render () =
let pixels = bitmap.Pixels
let black, white = 0xff000000, 0xffffffff
for x in 0..n-1 do
for y in 0..n-1 do
pixels.[x+y*n] <-
if (!game).[x, y] then white else black
do for i = 1 to 3 do game:= update() done; render ()
do async {
use handle = new System.Threading.AutoResetEvent(false)
do! control.MouseLeftButtonUp |> Async.AwaitEvent |> Async.Ignore
do! Async.SwitchToThreadPool ()
while true do
game := update ()
bitmap.Dispatcher.BeginInvoke(fun _ ->
render()
bitmap.Invalidate()
handle.Set() |> ignore
) |> ignore
do! Async.AwaitWaitHandle handle |> Async.Ignore
handle.Reset() |> ignore
} |> Async.StartImmediate
Application startup:
type App() as app =
inherit System.Windows.Application()
do app.Startup.Add(fun _ -> app.RootVisual <- GameControl(256))
Resources:
Source code: GameOfLife.zip (2.38 kb)
Just for fun, a clone of the 1980s arcade game Missile Command written in F# and deployed in Silverlight.
A language feature I have repeatedly found useful for games is state machines as sequences using yield. The following is used to define the path of explosions:
static member Path radius = seq {
for i in [50..2..100] do
yield radius * ((float i / 100.0) ** 3.0)
for i in [100..-1..0] do
yield radius * ((float i / 100.0) ** 3.0)
}
References:
MissileCommand.zip (4.65 kb)