The Factor game framework

May 11, 2009

For kicks, I felt like taking a couple weeks and trying to write some game infra­structure in Factor. You can see some of my handiwork in the terrain demo I recently threw together. If you have an OpenGL 2.0-capable graphics card, download a recent Factor build for Windows or Mac and run from the listener:

"terrain" run

(X11 isn't supported by some of the libraries yet.) Wait a few seconds and you should see this:

Use the WASD keys, spacebar, and mouse to walk, fly, and look around, respectively. Hit Escape when you get bored. Here's what I've added to Factor to make the demo possible:

The UI library

Factor's UI already provided a decent cross-platform interface to the OpenGL implementations on X11, MacOS X and Windows. However, the UI library does a lot of OpenGL state manipulation that gadgets have to work within (or work around) to behave alongside other gadgets. If you just wanted an empty window and a naked OpenGL context to have your way with, there was nowhere to hide from the UI's disapproving glare.

…Until now, that is. I shoved all that gadget management code into a handful of generic functions that you can override by providing your own subclass of world (Factor's representation of a window). I also added pixel format selection support, so you can ask for a window with stencil buffers, multisampling, high-resolution depth buffers, or other OpenGL features not required by the UI.

Game input

I wrote some bindings to DirectInput on Windows and IOHIDManager on MacOS X, and wrapped them in a cross-platform game-input library. Along with some support from the UI for grabbing the mouse pointer, the library provides raw polling access to keyboard, mouse, and game controller input.

Game loop

Writing a good game loop is hard. Now you don't have to—there's a game-loop library already there. Give it a timer tick length and a delegate object, and the loop goes off, drawing your world as quickly as your hardware allows and firing off a timer tick when necessary. The loop also provides a tick-slice fraction to the draw hook to allow the drawing routine to interpolate the game state between timer ticks.

A game-world class neatly wraps up the above components.

Remaining work

All this code is still pretty green, so don't quit your job to write games in Factor just yet. Here are a handful of things that need to be worked on:

The terrain demo itself is very basic too; it only generates one small segment of terrain, and the Perlin noise code I wrote takes much longer than it should to generate segments. Shortcomings aside, Factor's a lot of fun to work with. The FFI makes binding to system libraries trivial. Its code is well-compartmentalized, and even old, relatively crusty code like the UI internals is easy to work with and add features to. I don't think any of the problems above are going to be hard to fix over time.