I’ve been toying with the idea of creating games using a functional approach recently. I had a lot of fun last year writing a cut down PushButton Engine clone in Javascript, (which I’ve started rewriting) but since I’ve started learning Haskell recently I’ve really wanted to try out a more functional approach to making games.
First of all I should probably list some resources that I’ve found helpful so far with some descriptions:
Haskell In Space (pdf) – Has information and examples for moving spatials around and event handling (Haskell)
Purely Functional Retrogames – Has examples about how to handle state; in these articles state is threaded around.
Casting SPELs – Make an adventure game in LISP.
What I’ll present is just very early playing around and shouldn’t be taken as a ‘right’ way to do it as I’m still finding my feet with these concepts. I have a feeling that my keyboard handling code should use a Monad (as Haskell uses an IO Monad), and I’m not sure about using map and function composition in place of a traditional ‘update’, so any comments are welcomed!
This little program, when used in a page with a canvas element #canvas, and an image #image, will make some #images move around. W,A,S and D will affect their movement. Gist Here.
I’m just going to break down the more important parts of it here:
1. Replacement ‘update/render’ loop:
//we return a function here that closes over the initial local variables
//also means we can call _.delay with the same or different args to potentially evolve the loop
function iterate(input,spatials,context,image){
return function(){
context.clearRect(0,0,500,500); //still need to figure out where to move this
var _spatials = _.map(spatials,_.compose(processEvents(input),move,render(context,image)));
_spatials = _.filter(_spatials,inViewport);
_.delay(iterate(input,_spatials,context,image),1000/60);
};
}
In this snippet I’m using underscore’s _.delay, which works much like setTimeout. I’m currently combining updating and rendering for simplicity’s sakes, and so our main ‘iterate’ function takes everything it needs to update and render the spatial list. This is good in several ways, because it means we can modify the parameters to _.delay if we want to during execution, it allows for a neater recursive structure and it potentially allows us to create multiple iterate()’s with differing initial state (eg. var iterate1 = iterate(mouseinput,enemyspatials,otherrenderer,etc)). Further it means we can defer starting this loop if we want to.
So those are my initial thoughts about the structure – the next decision I’ve made is to use _.map on my list of spatials, and then make the functions that operate on those spatials composeable (via partial application in some cases). This makes the operations performed on each spatial clear and easily readable (and a one-liner), which I like. I’m not sure about the use of filter() for culling as particularly it means iterating over the list again. I would also like to move the context stuff out somewhere (a Render monad perhaps?).
2. Event processing and Rendering (but still taking and returning a spatial):
function processEvents(keys){
return function(spatial){
if(keys[68]){ spatial.vx += 0.1; }
if(keys[83]){ spatial.vy += 0.1; }
if(keys[65]){ spatial.vx -= 0.1; }
if(keys[87]){ spatial.vy -= 0.1; }
return spatial;
};
}
function render(context,image){
return function(spatial){
context.drawImage(image,spatial.x,spatial.y);
return spatial;
};
}
In both of these cases I’m using partial application to fix two inital bound variables and return a function that uses them, but itself takes only one parameter. This makes these functions composeable since render(ctx,img) returns f(spatial) -> spatial. I would like to make the ‘keys’ object more formally defined, and obviously it shouldn’t have hardcoded keyCodes – I would also like to try and implement some kind of IO Monad that would abstract this (once I’ve understood monads better!). Also this code should really create a new spatial and return that new spatial.
3. Move/Generic update rules:
function move(spatial){
spatial.x += spatial.vx;
spatial.y += spatial.vy;
return spatial;
}
Finally, this bit just moves a spatial by incrementing its 2d position vector by its 2d velocity vector. This part is likely to become far more complex once other rules are considered, but hopefully keeping the interface Spatial -> Spatial should mean that writing composeable update rules should be easier.
So that’s all really for this initial play around with the concepts, I’ll add more posts as I improve upon these initial concepts. Any comments would be welcomed, since material on functional programming in games seems sparse from my googling. So far I’m quite happy with the approach, since just by looking at the four core functions you can figure out what the program is doing fairly easily, and I find it structually and aesthetically quite pleasing