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.
Showing posts with label engineering. Show all posts
Showing posts with label engineering. Show all posts
Saturday, September 19, 2009
Friday, June 19, 2009
Cargo Cult Engineering
Process-oriented development achieves its effectiveness through skillful planning, use of carefully defined processes, efficient use of available time, and skillfull application of software engineering best practices. - Steve McConnellI'll come back to that quote eventually, but today's post is on cargo cults.
In my experience, engineering teams succeed because there's one or two engineers on the project that are smart, hard-working self-starters, but most importantly follow sound software engineering principles and are capable of taking stepping back and getting the big picture.
Smart, Hard-Working, Self Starters
There's ways of assessing this stuff. Personally, I think gradations of these attributes are mostly worthless. Programmers of average intelligence won't be able to tackle huge problems, or get a lot of features done, but having a smart but "unwise" (using that word as a catchall for what I'll describe in the sections below) engineer is worse than having an average-intellect but wise engineer.
Hard-working is good. But I think easy to assess. And if they don't work hard once they're in place, you need to fire them. If you can't fire them, because, say, you're in France, then that sucks. Your next job will be to get them to quit. Try transferring them to the Siberian Office.
Self Starters are handy, but again I don't think it's at the top of the list. A semi-smart, hard-working, self-starting programmer that insists on overengineering everything, following a fancy & convoluted development methodology, and is unable to assess the importance (ie context) of the parts that he is working on will build lots of great code -- that won't help your product ship or keep customers happy.
What's your goal? Are you capable of assessing context? As a manager, you want programmers that help your bottom line. That means quality code, but it also means code that you need, and code that makes your clients happy. Happy clients are more important than pretty code.
The Big Picture
Whether it's figuring out how one method fits into a class, one class into a module, one module into a project, one control into a web form, a folder or set of files into a hierarchy, one product feature into the next release, themselves into the company, their company into the industry, the product into the market, etc etc -- good engineers are capable of taking a step back and assessing context.
Bad engineers do cargo cult programming. They see the artifacts of good engineers, but they don't understand the principles behind it.
Sound Engineering Principles
Lists are popular. "7 Habit of Highly Effective People", "Top 10 Ways to Ship Better Software," the lists of core rules in methodologies, and the very frequent "Five Ways to Fit into Your Swim Suit for Summer" type stuff.
Lists are easy to make. Just observe for a little while. Pretty much anyone can make lists.
But lists aren't principles. Principles are difficult to apply. They're easy to state, but the whole trick with principles is that they must take context into consideration. Principles must also exist in a hierarchy; for each principle, there must be an antecedent principle that sets boundaries. The antecedent says why a principle is important, gives a guideline for the boundaries of the principle (where it makes sense and where it doesn't), and establishes a benchmark by which to judge the execution of a principle.
Take choosing good names for local variable. This isn't just one floating point out of hundred of practices that make for good software engineering. The list-maker will take this point and stick it into his six-page bulleted list of "Best Practices."
As a principle, one chooses good names because it aids in human parsing of code. Let's chase the antecedent principles here. Human parsing of code is important because it makes maintenance (extension and debugging) easier. Maintenance happens -- so why is it important to make it easier? Because it increases the quality of software and reduces the cost of development. Why are those things important? Why are they important on this product? The answers for quality and cost vary from project to project, and I could answer them in the abstract, but how you answer this question is what settles the boundaries of the principle.
Cargo Cults
Cargo cults mimicked the habits that they saw American military men executing. They thought that the motions themselves were what caused the airplanes to land, and the cargo to show up on the beach. Likewise, the actions that McConnell outlines in that quote above -- skillful planning, use of carefully defined processes, efficient use of available time, and skillfull application of software engineering best practices -- are habits. These are good habits, but I don't think they capture the important traits at all.
Specifically, "use of carefully defined processes" implies that browsing to some Six Sigma website and then handing down the printouts to your engineering team is sufficient for project success. That's just mimicking the habits of successful developers; it's not good engineering.
Labels:
engineering
Subscribe to:
Posts (Atom)