Category Coding

Digital art, Facebook 3D Graph Explorer, and more Project Lemma

My last two posts focused on general game development topics, but no longer. It's the end of the year, time to look back and review before looking forward to the new year!

Digital Art

First off, some fun diversions. In my pursuit of an art minor at Ohio State, I took a digital art class autumn quarter. The instructor let me use software I was already familiar with, so I didn't learn much. But the class gave me the motivation to plonck my butt down and make some art, which is all I really wanted.

C# for scripting - runtime compilation

I set out to add scripting support to Project Lemma the other day. End result: I can recompile C# scripts on the fly and cache the bytecode in DLLs. The best part: there's no special binding code, and no performance hit.

There are a lot of .NET scripting solutions out there. Here's a few I found in my research:

  • IronPython. Fully dynamic, kinda slow. Requires marshalling of some kind between the script world and .NET.
  • CSScript. Very well supported, includes Visual Studio extensions and shell extensions. Compiles C# to bytecode at runtime, with caching. Scripts cannot be changed once loaded.
  • Lua. The industry standard in scripting. From what I understand, a little challenging to get working with .NET.

I decided to try out C# runtime compilation. Really, C# is the best scripting language I could ask for. If I succeeded, I could keep writing the same code I've been writing, but I could recompile it and see it in action with a keystroke instead of restarting the game!

Physics and lighting fun

Sorry to post two videos in quick succession, but this was too fun not to record!

As promised: Component Binding "BEHIND THE SCENES"

In the wake of this brief description of my component binding system, I was asked to provide more details on its implementation. This article is my best attempt to do so!

This is a tale of intrigue, excitement, and wonder, in which I try to implement a component-entity system in C#, and stumble upon a remarkable paradigm that merges components with data binding.

Note: If you don't have at least a vague concept of component-entity design, read this article first.

Back on track

I finished refactoring with components, added a reflection-enabled editor and XML serialization, finally got real PCF shadow filtering, and started experimenting with a somewhat cel-shaded visual style. I've been busy.

The refactoring had a lot of positive side effects. Serialization is now relatively easy, as the state of each component is determined by its properties, which are usually simple, easily serializable value types. One interesting side effect of serialization is that object creation is now split into two parts: initialization, and binding. When creating a new object at runtime, a factory performs the initialization. When loading objects from XML, the XmlSerializer performs initialization. In both cases, the factory creates the necessary bindings between properties afterward.

Refactoring with components

Update: check this article for more in-depth details on Component Binding!

I've been refactoring my engine with the component-entity model, and things are turning out quite nicely. The one problem I always had with components was the way inter-component dependencies were handled. In the article I linked (one of the classics on the subject), the author says his components originally referenced each other through a component manager, but eventually they allowed components to store pointers to each other for performance reasons. In my mind, that's way too many concrete dependencies.

Tricksy closures

Do not be fooled by the elegant simplicity of the mighty closure! Behind its shiny dynamic veneer lies a powerful machine capable of destroying your immortal soul. Behold:

function GetOutputFunctions()
    {
        var outputFunctions = new Array();
        for(var i = 0; i < 4; i++)
        {
            var x = i * 2;
            outputFunctions.push(function() { alert(x); });
        }
        return outputFunctions;
    }
    var functions = GetOutputFunctions();
    for (var i = 0; i < functions.length; i++)
        functions[i]();

This will not output the first three multiples of two, as presumably expected. Instead it will output "6" three times, because the variable "x" is only allocated once.

Meshes of navigation

Update 8/23/2011: the source/executable for the navigation mesh .obj exporter is here. Import a mesh, set up the parameters (only simple mode is supported right now), and have it generate the mesh. It should output a .obj file in the directory where it was executed.

The AI system has finally received a massive and desperately needed update: support for navigation meshes. That means the bots shouldn't get stuck running into walls all the time, or running back and forth between waypoints like machines. I think this was probably the biggest weakness of the game up until now; the AI is still something of a problem, but it's much better.

Reloading, shadow mapping

Thanks to the Panda3D 1.7.0 shader generator supporting shadow mapping, and the awesome new BuildBot service set up on the Panda3D website, A3P now supports basic shadow mapping! Actually, the sun is just implemented as a giant spotlight with a 2048x2048 shadow buffer. Definitely not the most efficient or high-quality method, but certainly the easiest, and the results are acceptable.

Also new in SVN is a reloading mechanic. The shotgun, chaingun, and sniper rifle all have to be reloaded, with varying clip sizes and reload times. Of course, reloading units are highlighted as vulnerable, and they also beep furiously to make it perfectly clear they need to be shot at.

New gameplay

Sorry for the distinct lack of updates this blog has. A lot is happening right now with Stainless, and most of it's good. :)

First off, Stainless is going to have online multiplayer! Woot. Thanks to the fabulous work by the guys over at Panda3D, it may even live in a browser plugin on the SourceForge website. Either way, I came across a problem I never anticipated with online multiplayer: NAT punch-through.