Saturday, September 19, 2009

Game Tools with WinForms

I'm working on my RPG fairly actively this week. I've got maybe another week on the engine, and about that on the content, so it's close to being ready. As I implement more bits in the engine, I'm going back and changing the editor, too, so I'd figure I'd comment a bit on that here.

The RPG is retro, 2D, turn-based tactical combat, single-player, and single-character. Old school. I'm trying to make it not suck, but I'm using simple technology. It's called BlackThrone and it's up on the web so check it out.

The Editor

The editor was my very first WinForms app. I've been coding UIs and tools forever, and C++ since college, and Windows since the OS/2 days -- but C# for only a few years and barely much professionally until last year. So I was new to WinForms, and at the time was coming off of using C++ heavily for a couple years.

My point is, my god this app sucks. I didn't know about User Controls, so a half-dozen tabs, packed with dozens of controls each, are all in the main Form. The main form .cs file is HUGE. Blech. I didn't have any common methods of dealing with resources and graphics, so lots of the stuff was ad-hoc. It's interesting coming back to it now after having left it half-developed for a year.

There's a few things I wish I'd known and done then, and that's the point of this post.

UserControl

UserControl is your friend. It's basically a collection of other controls; checkboxes, lists, text entry fields, buttons, etc. It's great for taking a chunk of your UI (like the controls that would be on one tab of a control panel) and encapsulating them.

In my editor, each resource type is edited on a different tab of a TabControl. The main form contains a TabControl, and in each TabControl is a user control. This means that there's very little code in the main form.

At least, there's less now. I'm slowly refactoring the application, pulling each one of the tabs out of the main form and sticking them into user controls. This makes it much easier to ensure that I've got everything I need, didn't forget something; debugging is easier; etc etc.

Document Model

The editor actually started as just a map editor; the extra resources got shoved in. What I should have done (earlier, like when I added an editor for the second resource type) is added a document-type class.

The editor works on a set of files. The "document" is really a directory; each different type of resource is stored in a different file. One file for the world map, one file for all the towns and cities, one for dungeons, one for conversations, one for items, etc.

The main reason to pull all these in is interaction between the resources. For example, cities can contain treasure chests which can contain items. Hence, the city editor wants to get access to the list of items so that it can present that to the user. I started out hacking into the main form (which is where everything was stored) to get the item list, but even while writing that code I knew that was a fragile, ugly way to do it. I'm slowly refactoring each resource type out of that main form into the Document class.

Small Parts

This is really a generic Agile practice. Classes shouldn't be big.

One of the common functions I do is grab a tile (a 16x16 block of pixels) from my sprite sheet (which is a 256x256 image), create a Bitmap from that, and set it as the Image in a PictureBox. This is "instant feedback" that makes it easier to see which object I'm dealing with. Bad coding practice is to copy and paste these few lines of code from here to there.

My refactor was to create a TileSheet class, and add a method to that to pull a Bitmap out -- and another method to draw a tile into the current Graphics object (eg in an OnPaint event). The TileSheet itself is small -- it's a small part.

Recommendations

If you're building an indie game, I really recommend using WinForms and C# to build data editors. If you're just starting out with WinForms, I recommend reading a book first -- having an idea of the things you can do makes it easier to choose the right thing to do. I started coding first, hacking together sample code from the net. The book I eventually bought, and one I really liked, is _Pro .Net 2.0 Windows Forms and Custom Controls in C#_ by MacDonald, on Apress.

And when you do start coding, think about putting together a document model. In my day job, having a good doc model is critical for good, clean architecture, and it's the same for my home projects.

No comments: