Pandemonium

July 28, 2008

Efficient Development – part three

Filed under: Games Development — bittermanandy @ 11:54 pm

Neither of the articles in this mini-series so far have been particularly revolutionary, though I do think I’ve implemented them in an elegant, almost effortless way. Most pro developers out there will have used tools much like them on most of their games; but I think they represent the kind of “obvious” tip that hobbyist developers never get told about, so hopefully they will have been of interest to at least a few people out there. The next tip, though, is something so blindingly obvious that every non-trivial development effort will have something like it. Or so I thought, until I (briefly) worked at a studio where there wasn’t much like it at all, and what little there was took fifteen lines of code where one ought to have been enough. In particular, it reduced 3D development to guesswork, and it showed in the quality of the game. So if you haven’t got stuff like this in your toolkit already – do it now! (Or, wait for a couple of days until I publish my Kensei.Dev code, then you can use that).

Pictures are worth a thousand words so here you go (you’ll want to follow the link to see it in detail):

Dev shapes and text

Dev shapes and text

This is a screenshot from the map editor mode of Shihan, a game which will, sadly, never see the light of day; XNA may be brilliant, but it eventually became clear that one person still can’t do the work of forty, and it would need forty people to make Shihan what I wanted it to be. That’s OK – lesson learned before too much time had been lost, and Pandemonium is a much more realistic target.

There’s quite a lot going on in the screenshot. In addition to the ground textures (from here), the skybox (from here) and the tree (procedurally generated by the wonderful XNA library here) you can see a whole bunch of other stuff:

  • In the top left is text that is printed as though it were on a page. This is useful for messages to the developer and stuff that remains in view over several frames. In this example, it prints the current camera position and the frame rate (essential information at all times). This uses Kensei.Dev.Text.Print.
  • In various locations across the screen is text, printed at a position in 3D space. This is invaluable for showing precise vector co-ordinates, as seen in this screenshot, and other data that needs to be readable but positioned in space. It uses an overload of Kensei.Dev.Text.Print.
  • In the centre of the screen, in red, green and blue are lines indicating the 3D axes, using Kensei.Shape.Dev.Axis. Note XNA’s leftright-handed coordinate system!
  • The green lines form the edges of a box around the currently editable ground tile. You can also see the red and yellow lines, which indicate the shapes formed by the control points and polygon edges of the ground respectively. Boxes and lines are invaluable for showing regions of the game world without blocking the view and are drawn with Kensei.Dev.Shape.Box, Kensei.Dev.Shape.Line and a number of others.
  • The solid white 3D arrow in the centre of the view indicates the light direction. Solid shapes, including boxes, cylinders, spheres, frustums, etc. are also useful for showing regions and can even stand in as “programmer art” for game objects, as you’ll see in the next screenshot. Above, you can see Kensei.Dev.Shape.Arrow; below, the player is represented by a Kensei.Dev.Shapes.Capsule.
  • Below also shows a couple of hollow spheres (Kensei.Dev.Shape.Sphere) indicating the minimum and maximum ranges of a currently playing test sound. Note how text positioned at the same location as the sound gives us valuable information about it.
  • Also available are frustums, cylinders, cones, crosses, and triangles, each in wireframe or solid, and in whatever colour is required.
A Dev Capsule standing in for the player character

A Dev Capsule standing in for the player character

 It’s practically unheard of for me to be running the game during development and not have some of this stuff turned on (controlled using Kensei.Dev.Options, obviously). It’s fundamental to the game programming art (especially in 3D but it’s useful in 2D too), and trying to work on that game without it was a nightmare, it’s as simple as that.

By now you will not be remotely surprised to learn that the code for all this is pretty simple to implement. Here, for example, is the entirety of the rendering code for our stand-in player character:

    Vector3 bottom = m_position;

    bottom.Y += HumanRadius;

    Vector3 top = m_position;

    top.Y += HumanHeight – HumanRadius;

    Kensei.Dev.Shape.Capsule( bottom, top, HumanRadius, playerColour, true );

Or as another example, the sound source includes code to help show where sounds are coming from as follows:

    if ( Kensei.Dev.Options.GetOption( “Audio.ShowSoundPositions” ) )

    {

        foreach ( CueInstance cue in m_attachedCues )

        {

            Kensei.Dev.DevText.Print( m_xactEmitter.Position, cue.ToString(), Color.LightBlue );

        }

    }

 

    if ( Kensei.Dev.Options.GetOption( “Audio.ShowSoundDistances” ) )

    {

        foreach ( CueInstance cue in m_attachedCues )

        {

            Kensei.Dev.Shape.Sphere( m_xactEmitter.Position, cue.MaxDistance, Color.LightGreen, false );

            Kensei.Dev.Shape.Sphere( m_xactEmitter.Position, cue.MinDistance, Color.Lime, false );

        }

    }

It really doesn’t get much easier than that.

Behind the scenes it’s pretty straightforward too: the Kensei.Dev.Shape (and Kensei.Dev.Text) static classes track what they are asked to draw during the frame, then render it all in one batch during the Draw method. Working out how to draw some of the more complex shapes was a bit of a pain, but not horrendously so and anyway if you use Kensei.Dev when I release it, that will all be done for you.

I hope you understand what I mean by Efficient Development by now. It’s not just having options in your game; it’s the ability to add options with one line of code, and control them during debugging with one mouse click. It’s not just having a command line interface; it’s the ability to add a new command to it with less than five minutes work and have it available forever after. It’s not just being able to draw shapes – it’s the ability to do so in one line of code and turn them off and on at will, so you can visually understand why your 3D code is misbehaving or put off creating complicated 3D models until later. Efficient Development is putting in a small amount of work up front to enable big gains later. It’s also knowing when to stop – almost all of the stuff I’ve written could be polished further (and you are encouraged to do exactly that if you decide to use it), but being a one-man team it’s enough for me at the moment. Efficient Development is about finding the balance between creating time-saving tools, and spending so much time making time-saving tools that you never quite get around to finishing the game.

Speaking of which: in the next and final part of this mini-series I’ll make the Kensei.Dev code available for download, and cover a few final miscellaneous tips; then we’ll move onto something more exciting.

“Step by step walk the thousand mile road.” – Miyamato Musashi

9 Comments »

  1. Lots of good advice, and the code will be helpful to new XNA programmers.

    Quick nitpick, XNA math libraries assume a right handed coordinate system, not left handed?

    Comment by Jare — July 29, 2008 @ 5:45 am | Reply

  2. Drat. You’re quite right. I’d always used a left-handed system before and thought of XNA as using the “wrong way around”, I guess I’m now used to right-handed so got confused which one I was more used to using! Good spot.

    Comment by bittermanandy — July 29, 2008 @ 10:02 am | Reply

  3. Very well thought out… I think I will follow the path of least resistance and wait for your Kensei.Dev code. NUnits can only get you so far! I’m definitely doing too much Tweak, Run, Repeat.

    Comment by Evan — July 29, 2008 @ 5:18 pm | Reply

  4. I just wanted to say I’m loving the tone of this blog so far. Thanks for taking the time to share some “pro tip” with us!

    Comment by Dan — July 29, 2008 @ 6:52 pm | Reply

  5. Great stuff there, it’s great to hear such simple learned advise laid out so plainly.
    As you mention unit testing in your blog are you also going to cover some practical advice or even include some (stuff) in your Kensei.Dev code?

    Comment by Darkside — July 29, 2008 @ 7:23 pm | Reply

  6. Great blog. Three posts in, and up there with Sir Hargreaves already. Can’t wait for more (and that code you keep promising us!)

    Comment by Acemuzzy — July 29, 2008 @ 9:18 pm | Reply

  7. Darkside: um, unit testing is currently something I preach about rather more than I practice… Kensei.Dev is currently a unit-test-free zone! Possible material for a future post though (and something I know should do more of).

    Acemuzzy: cheers for the kind words, but Shawn is a hundred times the XNA master than I am!

    All: thanks for the comments, it’s nice to feel appreciated!

    Comment by bittermanandy — July 29, 2008 @ 9:38 pm | Reply

  8. Those are incredibly useful explanations of runtime fiddling and some great advice. I’m a newbie at XNA, C# and .NET (but having used C in the past, it’s a terrific prototyping language), so thank you for your blog entries. They’re bookmarked.

    Comment by Scott Macdonald — July 29, 2008 @ 9:55 pm | Reply

  9. This is good stuff. Will get this integrated in my dev build ASAP. Any chance of you and Shawn doing a book? 😉

    I’ve found myself spending a lot of time tweaking my dev framework and i think this article vindicates my approach!

    Comment by cannontrodder — July 30, 2008 @ 12:08 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.