A Platform game in F# and SpriteKit – Part 6 – Death

If there’s one thing we can all be certain of in life, it’s death. And so the same rule must apply to our dude. It’s been good knowing you little guy.

F# shines again

The last few posts have been back on the “How SpriteKit works”, but this time I’m firmly back in “Why F# rocks” territory.

The shining example of F# goodness? First class events (again!) and discriminated unions.

Let’s start with the latter – if you haven’t come across discriminated unions before, then you can think of them as enums on steroids. Here’s our example today –

type LevelComplete = | Died | Continue

Now this is the most basic kind of discriminated union, which doesn’t give us anything more than an enum. But later I can embellish this to do something like:

type LevelComplete = | Died of int (*Final Score*) 
                     | Continue of int * int (*Score & Lives remaining*)

In short – it allows us to classify data under the LevelComplete type and pattern match to extract extra data. If you’re new to F# the concept may be new to you (buy this book NOW)- if you’re an old hand then you probably already know more than I do.

So we now have a type – but how do we use/consume this?

Well just like how we used the tap as an exit condition for the intro screen, or a timeout on the game over screen, we can set some rules in our update. For now the rules will be simple –

If the player falls off the bottom of the screen -> Died
If the player runs a certain distance -> Continue

Here’s the code:

let levelCompleteEvt = Event<_>()
use _ = scene.DidSimulatePhysicsEvent.Publish.Subscribe(fun _ -> 
    scrollNode.Position <- PointF(320.f - player.Position.X,0.0f)
    parallaxScrollNode.Position <- PointF(-player.Position.X / 2.f, 0.f)
    if player.Position.X > 10000.f then 
    levelCompleteEvt.Trigger Continue
    if player.Position.Y < -100.f then
    levelCompleteEvt.Trigger Died
)

As you can see we trigger an event to say what happened (new code highlighted in bold) (did I mention before first class events in F# are cool?). Then like the other async workflows we AwaitEvent on the new event (why oh why oh why was this omitted from C# async/await?).

let! levelComplete = Async.AwaitEvent levelCompleteEvt.Publish
return levelComplete

But then we return the result – this way we can control flow in that main game loop –

//Define the loop
let rec gameLoop() = async {
   do! startScreen()
   let! levelEnd = level1()
   match levelEnd with
   | Continue -> do! success()
   | Died -> do! gameOver()
   return! gameLoop()
}

Now you can see that we are able to reward the player for succeeding, and humiliate them for dying.

I’m not going to cover the awesome success() screen – you should run it an experience it’s awesomeness :). Hint: it uses SpriteKit particles, which Dave Thomas wrote about righthere.

More levels

Now I’m not going to go into too much here, other than lay some groundwork, but as a goal it would be nice to

  1. Support multiple levels
  2. If it was easy to write levels
  3. Be scalable

In my latest checkin I’ve added in some comments in the level() async workflow to highlight the level loading code (which should be changeable) and the player code (which should be the same for every level).

There are a couple of ways I can think of to handle multiple levels:

  • Have level take a higher order function and I could pass in functions to build levels (this doesn’t address #2 as every function is going to be bogged down in SpriteKit code)
  • Define an external file format (probably XML or JSON based) – this supports #1 and #2, but changes to the format are very brittle and not too scalable.
  • Define an internal DSL to define the data and a parser to turn the data into a level – I think this addresses #3 as breaking changes will force the project to not build – less chance of runtime errors or breaking changes. Once again, this plays right into F# strengths.

If anyone has a 4th suggestion, please feel free to post a comment!

So next time I’ll probably build a simple DSL to represent a level and then cover loading it in in a future post.

Code for today

All the code

Advertisements

About thedo666

Software developer trying to learn a new language - English!
This entry was posted in F#, iOS and tagged , , , . Bookmark the permalink.

One Response to A Platform game in F# and SpriteKit – Part 6 – Death

  1. Pingback: F# Weekly #42, 2013 | Sergey Tihon's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s