updated May 11, 2009 11:32:03 PDT
For kicks, I felt like taking a couple weeks and trying to write some game infrastructure 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:
(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.
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.
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.
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 game loop doesn't fire ticks very steadily yet. There's noticeable unevenness when walking around in the terrain demo. It needs some tweaking to interact better with Factor's thread scheduler.
- game-input doesn't support Linux or the BSDs yet. It's been a while since I've used any of those platforms on a desktop machine, and I don't know what the hip way of handling raw input is these days. And I'm afraid to ask.
- I haven't investigated audio at all. Factor has an OpenAL binding that's been around for a while and has been used for a couple of simple demos. However, OpenAL is much lower-level than something like fmod, and you'd need to build a lot on top of it to use it in a game.
- Factor's UI has a set-fullscreen function, but this just hides system decorations and resizes the window to cover the screen. At some point I'd like to make it support seizing the screen, changing the resolution, and using a true fullscreen OpenGL context.
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.