Menu

I know what you’re thinking. You really like the look of F# but your legacy brainfuck applications are stopping you from making the jump. Well worry no more, the brainfuck type provider is here to save you.

The type provider allows access to both the console output as well as the data stored in memory at the end of the program’s execution. It’s really easy to use as well.

Last night after presenting at F#unctional Londoners, I got the chance to talk to Ross McKinlay (@pezi_pink) and the topic of job interview questions came up. Ross claimed that for most jobs the simple Fibonacci test doesn’t really do enough to filter out applicants and he instead proposed 2 other questions which he’s seen used to great effect, so I decided to try and implement them in F#. (more…)

This is just going to be a really quick post on how to solve this problem I get occasionally and it fits in with what was made in the post on using MonoGame with F# interactive. When you try and compile an F# project, you may get a series of warnings telling you that the file copy operation timed out. Then after 10 of these warnings you get an error and a build failure. This error probably means that the library you are trying to use was referenced in the F# interactive window by using the #r directive.

To solve it you have to simply reset your interactive session by right clicking within the F# interactive window and selecting reset interactive session. Unfortunately there doesn’t appear to be a way of dynamically unloading any assemblies and so you will end up losing your current interactive session.

If you’ve tried F#, you’re probably aware that there’s also a REPL to interactively evaluate expressions. It’s also useful for quickly modifying game levels. The normal process for game level design has been to use a level editor such as Tiled and then load it in to your game. However, we then don’t have things like our character in game to test whether a platform is reachable or whether a power up is too hidden. This meant that we would normally have to edit the level, reload the level and then get back to our original position. Instead, imagine being able to run your game and then add new level items on the fly.

As it currently stands the platformer we’ve been working on seems pretty bland. When we move around, nothing really happens with our player so let’s add some animation to him. We’ll aim to make it as functional as possible so no side effects.

The first thing we need is a type that reflects all of our associated data for an animation. So I’ll be adding most of this in a new file called PlatformerAnimation.fs which you’ll need to add right at the top of our files list. Then we’ll represent it like follows and add a function to create an animation.

Next we need to update it and return an appropriate new state given that we know how long it’s been between updates. All we have to do is check to see how long it’s been since an update and increment the frame counter and then if that’s too high, we set that back to 0.

Let’s change the signature of our WorldActor as well so that everything has an animation rather than a static texture. We can do this because a static texture can be represented by an animation with a single frame. We’ll also need to add a function to update the actor’s animation.

Finally we need to update our PlatformerGame file. We need to change the Update function to now handle the new Update function so we’ll chain that onto the end. We also need to change our DrawActor function to now use the animation drawing.

Introduction

In this guide, I’ll walk through how we can make a game with very simple platformer physics using F# and MonoGame. This will be a Windows desktop game which runs on OpenGL but you can easily port it to any other platform that MonoGame supports. The code will be available every step and the Github repository will be tagged so you can pick up from any step. Repo.

Setting up

There’s 2 key things I’ll be using throughout this. Visual studio 2012. I’ll be using Ultimate but any IDE that supports F# will work (even Xamarin studio). We’ll also need Monogame. MonoGame is an open source implementation of the Microsoft XNA framework to the extent that it’s essentially a drop in replacement. It’ll also run on pretty much any platform ranging from Windows Desktop to Windows Store to iOS and PS Vita (unfortunately the PS Vita doesn’t technically support F# though). So all you need to do here is to install the MonoGame framework available at monogame.net/downloads

Part 1 – Creating the project

We’ll need to first create an F# Windows application, so open Visual Studio and go File –> New Project and choose an F# Windows Application. Call it whatever you like but I called mine Platformer. You should now have a file called Program.fs which when you run will print the command line arguments and close.

Now let’s add the references. Right click the references folder and add reference. Now navigate to where you installed MonoGame and choose the following binaries to add from the WindowsGL folder (this is probably C:\Program Files (x86)\MonoGame\v3.0\Assemblies\WindowsGL if you followed the default installation):

Monogame.Framework.dll

Lidgren.Network.dll

OpenTK.dll

Tao.SDL.dll

Now right click on the project and add an existing item and choose the SDL.dll from the same directory. You’ll need to set the build action to none but copy to output directory in the properties.

Part 2 – Point of entry

We’ll now need to actually create a game which we’ll run. As the file order is important in the F# compiler, we’ll need to add a new file called PlatformerGame.fs above Program.fs. Once we’ve got that add the following code.

This is the very base of what we’ll be using. We essentially just inherit from the base Game class and then initialise a few variables to handle all of the drawing. We also clear the screen to a solid blue in the Draw method. To use it, in the main entry point in Program.fs we’ll need to run our game as follows.

open PlatformerGame
[]
let main argv =
use g = new Game1()
g.Run()
0

Here we’re just basically saying run the game. Now when that’s done you should end up with something that looks like the following.

Part 3 – Representing objects in the world

Our world will be made up of lots of 1 thing, we’ll call it an actor. An actor can be a wall in the level, it can be a player or even an enemy. We’ll then add properties onto this that help us identify it. We’ll be making a few assumptions though. First of all, we’ll be making a tiled platformer, so all collisions will be based on rectangles. Second, we’ll have only 2 types of physics bodies (static and dynamic). Finally for now, we’ll only have 2 possible player states; jumping and nothing. We’ll call our world objects actors, so that we don’t cause any naming conflicts with the keyword object.

So create a new file above PlatformerGame.fs called PlatformerActors.fs. This is where we’ll store our code relating to representing our players. So now add the following code.

Here we’re creating a couple of discriminated unions which are our properties and then a record type for our actor. You’ll see why a record type is useful later on. As we’re representing all our world objects with this one type, we need a way to tell if something is invisible or not, for this we use an option type. We also add a couple of member variables called Bounds and DesiredBounds which are later used to calculate whether or not it is touching something else.

Part 4 – Creating and drawing actors

We’ll create a simple function which is used to create our actors as follows. It essentially wraps our constructors into a function. So add the following to PlatformerActors.fs.

We’ll create a list of arguments which we’ll pass to the LoadActor function later. Then we can create a mutable list of actors which we’ll use our list of arguments to map from lazily. By doing it lazily, it avoids creating lots of mutable states and potential null references which are only filled later in the LoadContent method. Instead, we’ll simply force the result in the LoadContent method. In the repository on GitHub, there are a couple of content files called player.png and obstacle.png, you can either use these or create your own. So add the following to the Game.

This will essentially check to see if we have a Texture as noted by IsSome. If there is then we can draw it, otherwise we’ll skip it. Now when you run it you should see the following.

Part 5 – Adding gravity

The game’s a bit dull at the minute. Not much happens at all. Let’s add some gravity. We’ll add a file called PlatformerPhysics.fs below PlatformerActors. Here we pass in an actor and if it’s dynamic then we add a downward acceleration. We also need to then resolve all of our velocities by adding any new velocity to the current position. So add the following to that file.

We need to pass in a gametime so that we can work out how far to move. Whilst we could say just move forward 5 each time, if somebody was running at 60 frames per second they would move twice as fast as someone running the game at 30 frames per second. The one key thing to note in here is that we need to take a reference to the current list of world objects. If we were to try and use map on the lazy value, then it would throw an exception. We now need to call this function in our update as follows.

You should now see your objects fall if they were set to be dynamic, but they fall through our static objects. Next we’ll be adding a way to check for collisions.

Part 6 – Detecting collisions

Here comes one of the trickier parts of this. We need a way to stop our player from walking through walls. We’ll do this by passing all of our world actors and then splitting them based on type. Static objects can intersect static objects because they can’t move. A dynamic actor can touch a dynamic actor as they may need to handle the likes of enemy collisions. Then for every dynamic object, we take it’s desired position, which is where it would be if there wasn’t anything in the way and check to see whether it touches anything. If it does then we don’t move it completely otherwise it’s free to go. I’ve added it to the PlatformerPhysics file.

As you can see we take the world objects and split them into static actors and dynamic actors. Then for every dynamic actor, we fix it’s collisions and then add it to the list of fixed collisions. We repeat this until all actors are fixed and then we return our list. To check our collision we get the intersect of our 2 objects and then fix in the correct direction. Let’s also add the call to this in our Update which should now look something like this.

Part 7 – Handling input

To control our game, we’ll just be using our keyboard. We’ll write a function which takes in all the pressed keys and then calculates whether or not we need to do anything with them. Let’s create a new file called PlatformerInput.fs. Add the following.

Here we take in a game actor and a GameTime, then if the actor is a Player, we can operate on it. We also need to ensure that if the player wants to jump then they can’t already be jumping. This then needs to be called in our update. We need to make sure that we call it before the collision checking though so that we can’t walk through walls.

If you run that now though, we’ll move even if we aren’t pressing any buttons. So we need to add some friction. Once again in PlatformerPhysics, let’s add a function called AddFriction which takes our actor and reduces our speed by 5%. You can tweak this to whatever you like though. You should end up with something like this, then make sure you call this in the Update with a map.

Final thoughts

Hopefully this has given you some idea of how you can create a simple game with F#. There’s a lot that’s not been implemented but I’ll leave that as a challenge to you. You could add enemies with AI. You could create a simple level editor to be able to export your maps, or you could use something that already exists like Tiled. Also as it stands, we’re working in a very small map. Having a camera to move around which follows the player allows larger maps.

All the code in this tutorial is available on GitHub here. The tags are available for the end of each step as well, so you can always pick up wherever.