Pac[Metro]Man - Recreating PacMan for Metro with a little help from F#


Today's wild Wednesday post is an interesting mix of languages and things, all thrown together as a Metro game (Yeah, I know it's not Metro Monday, but still...)

Today's project mixes Metro style app development, Portable Libraries, C#, F# and the always fun to play PacMan!

Pacman Tiles

Back in January I built a sample Pacman maze script in F# to use at a Pacman Kata evening with the F#unctional Londoners group. Coincidentally there’s another Coding Kata this Thursday 26th July at Skills Matter. Anyway a couple of weeks ago I started playing with the sample again on the train to and from work, filling in some of the gameplay.

You can play the latest version with your cursor keys and 9 lives below:


Windows 8

As the sample runs in Silverlight I thought I’d also try it out on it’s cousin WinRT. WinRT lets you build Metro apps on Windows 8. The transition code wise has been pretty straight forward and I now have a tile for the game appearing on my Windows 8 start page:


Multi-targeting Silverlight and WinRT is the route I decided to go down which allowed me to develop the game on my laptop running Windows 7 with Visual Studio 2010. Then I periodically tested it out on a desktop box running the Windows 8 Preview Release using Visual Studio 2012. Visual Studio 2012 does run on Windows 7, however WinRT does not.

The WinRT version of the app is implemented in F# and C#. The game part is written in F# as a portable library and the plumbing in C#. There’s a great walkthrough on Creating a Portable F# Library over on MSDN which describes this direction in some detail.


Full Source

The full source code to the game is publicly available on BitBucket:

A single file playable script version is also available on F# Snippets:





One interesting thing was how it scaled. For example, here's the app snapped, where it remained fully playable;


Here's a snap of the Solution, showing off how F# and C# were mixed, using a Portable Library project.


One of the meta items in the project was how F# was used to generate the PacMan logo's/images.


#r "System.Drawing.dll"

open System
open System.IO
open System.Drawing
open System.Drawing.Imaging

let drawPacman (bitmap:Bitmap, x:int, y:int, size:int) =
    let width, height = bitmap.Width, bitmap.Height
    let graphics = Graphics.FromImage(bitmap)
    do  graphics.Clear(Color.Black)
    let points = 
        let right = x + size
        [|right,y + size/2 - size/4;right,y + size/2 + size/4; x + size/2, y + size/2|]
        |> (fun (x,y) -> PointF(float32 x,float32 y))

open System.Windows.Forms

let show (bitmap:Bitmap) =
    let form = new Form()
    let box = new PictureBox(Image = bitmap)
    box.Width <- bitmap.Width
    box.Height <- bitmap.Height
    form.Width <- bitmap.Width
    form.Height <- bitmap.Height + 32

//let root = @"C:\Users\Moon\Documents\Visual Studio 2010\Projects\pacman\PacMan.Xaml\Assets\"
let root = @"C:\Users\Phil\Documents\Visual Studio 2012\Projects\pacman\PacMan.Xaml\Assets\"

do  // Logo
    let path =root + "Logo.png"
    let bitmap = new Bitmap(path)
    drawPacman(bitmap, 42, 38, 64)
    bitmap.Save("PacMan_Logo.png", ImageFormat.Png)

do  // SmallLogo
    let path = root + "SmallLogo.png"
    let bitmap = new Bitmap(path)
    drawPacman(bitmap, 3, 3, 24)
    bitmap.Save("PacMan_SmallLogo.png", ImageFormat.Png)

do  // StoreLogo
    let path = root + "StoreLogo.png"
    let bitmap = new Bitmap(path)
    drawPacman(bitmap, 5, 5, 40)
    bitmap.Save("PacMan_StoreLogo.png", ImageFormat.Png)

do  // SplashScreen
    let path = root + "SplashScreen.png"
    let bitmap = new Bitmap(path)
    drawPacman(bitmap, 200, 42, 214)
    bitmap.Save("PacMan_SplashScreen.png", ImageFormat.Png)

do  // Icon 16x16
    let bitmap = new Bitmap(16,16)
    drawPacman(bitmap, 1, 1, 14)
    bitmap.Save("Icon16x16.png", ImageFormat.Png)

do  // Icon 32x32
    let bitmap = new Bitmap(32,32)
    drawPacman(bitmap, 2, 2, 28)
    bitmap.Save("Icon32x32.png", ImageFormat.Png)

do  // Icon 48x48
    let bitmap = new Bitmap(48,48)
    drawPacman(bitmap, 3, 3, 42)
    bitmap.Save("Icon48x48.png", ImageFormat.Png)

do  // Icon 128x128
    let bitmap = new Bitmap(128,128)
    drawPacman(bitmap, 8, 8, 112)
    bitmap.Save("Icon128x128.png", ImageFormat.Png)
    show bitmap

Okay, what about for the non-Metro dev's? Well there's VS2010/SilverLight, Windows Phone and XAML fun for you too!


If you're looking to expand your development language repertoire and looking for fun way to do it, looking for examples of how to mix and match C# and F#, looking for examples of F# and SilverLight or finally F# in a Metro world, this project has all that and more...

The Discussion

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.