Categories
Game Development

State design

I’ve been thinking about a good state design system lately and how to address common problems in other games.

The problem in most other games is that states are designed to be modular, but don’t turn out to be, both in functions and in data.

Functionally, a game may have an options state, and a game state, and may later decide to show the options state while running the game state. If this is not defined in advance, the likely fix is just to call the render function of the options state from the game state. It works, but it’s poor design that can easily cause bugs. For example, the render function may rely on data setup by the enter function of the state. If not now, then maybe later when someone adds it and didn’t know about that dependency.

The same holds true for data in non-obvious ways. When I was working for nFusion we had to access game-specific data from the main menu screen, in order to determine if the continue button should show up or not.

You could just make the data global, or essentially global, such as putting it in the “Game” or “Application” class. However, this is bad design. You want to make data accessible to exactly the classes that need it, no more and no less. One solution is to put the data into a higher level shared class. For example, at my job we have an AI class and various controllers that interact with it. CONTROLLER SPECIFIC data sometimes needs to be shared between controllers that were designed to be independent. This generally goes in the AI class, which is bad design. We now have this huge AI class with a ton of data members, half of which serve some special purpose.

The solution I came up with is pretty simple but I think solves these problems with a minimum of complexity:

The application class contains a state manager
The state manager contains a stack of states, which are instantiated or deleted as needed.
States are unique in the state manager. No more than one instance of a particular state can run at the same time
States are independent and contain implementation functions and capability functions.
States refer to each other through enumerations, rather than pointers.
When a state manager gets an event (keypress, render, update), it goes to the state manager, which then processes it to each state in reverse order. For each of these, a state can trap an event so it does not progress to higher level states.
Data that is shared between states is held in a reference counted pointer.

How this works is easiest to show in an example:
Game states, calls state manager to create the main menu

The main menu does not already exist. It is created and put on top of the stack.

Query, update, and render calls to go the state manager, which sends the events to the main menu, which handles the events.

The user presses options. The main menu state tells the state manager to create the options state. As it does not already exist, it is created and put on top of the stack.

Since events are processed in reverse order, the main menu state renders and updates first. However, the main menu state queries the state manager and finds it is not at the top of the stack. Therefore, it renders a dimmed version of the background. All events are passed through to the options screen except the keypress “alt-z” which plays a main menu specific easter egg sound.

The options screen updates as usual.

Now the user presses esc. The options screen interprets this as “Remove myself from the state manager” and the user is back at the main menu.

The user presses “Start game” which tells the state manager to remove the main menu from the stack and create the game state.

In the game state, the user now brings up customize ship menu (which was also available from the main menu). The game continues to run in the background fully, but keypresses and mouse presses are not processed. The user then brings up the options screen while the customize ship menu is open.

The customize ship menu is not designed to run unless it has primary focus (top of stack). Therefore, the allow render and allow update calls return false. The options screen shows up over the game screen. The user presses esc, and as before the options screen is removed. Since the customize ship menu is next on the stack, it shows up again and none of the user’s changes were lost.

The user presses esc again, and goes back to the game.

Shared data will be in singletons that are referenced counted and delete themselves when they are no longer used. States will get a pointer to the singleton when they are created, and release the pointer on free.

Categories
Game Development

Next steps in technical investigation

I finally have 3D graphics appearing in both IE and Firefox. It takes some setup by the user. Once I pay the fee (IE) and provide an installer (Firefox) this should be easier.

Now that I have 3d graphics appearing in the webpage it’s time to test out other major, risky features:

Input
Sound
Level editor

I’ll look at these over the coming weeks but I don’t think any of them will be a serious problem.

Categories
Game Development

Some time wasted, some progress made

Last night, with a helpful download link from someone on the Games-L mailling list, I got a Mozilla plugin working in about an hour. I was pretty happy about that, because the same task with Active X took a week. I spent another hour trying to figure out how to get the data in the SRC tag into the C++ code but got nowhere. Thinking this should be something easy, I ask around in some online lists and go watch Battlestar Galactica.

This morning I check my email, expecting to find numerous relies about how stupid I am and pointing out some obvious answer. However, aside from spam there was nothing there. So I get back to work (it’s 8AM or so). My initial guess was that you were passed the file data in the startup code. This is not an unreasonable assumption in my opinion. I pursue this guess for about an hour but just can’t find the file data anywhere. I browse the web, find someone elses’ open source plugin, figure out how they downloaded the file, and painfully converted that to work with what I had. I set it up as a synchronous download, so I just get the whole file in one function call. It’s 11:00 AM now. As the final step, I decide to try out asynchronous download and add a progress bar. I change my download to asynch and suddenly I get two asynch reads rather than one. It turns out the original file was downloading asynch the whole time. Great…

I’m done dealing with the Mozilla plugin at this point. My next step is to get the custom LZMA pack that I wrote and convert it from file->file to memory->memory. This is harder than it sounds, because the LZMA author decided to implement his own version of cross-platform COM. So rather than the simple step of changing a few fopen lines, I now have to implement 2 custom COM classes as a memory stream class and painfully debug them. This was a risky stage in development due to the difficulty and reliance on 3rd party code. I was lucky that it worked without having to go too level because I would have given up and used Winzip instead rather than try to debug COM. Once again I’m thankful for open source libraries. This would have been impossible to accomplish otherwise.

Now that it works I have 3 different ways to launch the game. The Mozilla plugin downloads the data and starts a thread. ActiveX, for IE, gets the data from a resource and starts a thread. The EXE launcher just loads the regular data files from disk and runs in the default thread. They all run the same game code so in theory, though not very well in practice, I should be able to work from one launcher and have the other two automatically work.

Solution with firefox launcher

The next step is to finish up my resource manager, so fopen calls to Irrlicht go to that instead. If and when that is done I can finally see models in the browser.

Categories
Game Development

Developer roadmap

Stage 1: Technical investigation
2-3 weeks
I am going to implement a cross-section of the game, with all features, but basically implemented. This will let me know what kind of hoops I have to jump through and what is not possible.

Stage 2: Game design
2-4 days
I will fully flesh out each element of the game design into a full design doc.

Stage 3: Code design
1 day
Based on the game design, I will design classes, structures, and perhaps variables to represent this in an easy to use, extensible, and maintainable way.

Stage 4: Coding
3 months
I’m going to do the multiplayer part last. Normally this would be the wrong approach, but it works here because there is only one code author and it avoids a lot of overhead restarting and starting the server.

Stage 5: Assets + polish + design
2 months
This is the time to hire artists and sound designers. A lot of game design occurs at this point as well, since the initial rough values will need to be tweaked out with features added and dropped based on how well they work. If I can find someone affordable, I could hire an artist earlier during the programming stage.

Stage 6: Closed beta / bug finding
1 month
I might have to do the whole NDA deal. This will get all the major bugs out of the way so when open beta starts I’m not swamped beyond measure.

Stage 7: Larger beta
1 month
Here comes server load balancing, and a better opportunity to find exploits.

Stage 8: Open beta
3 months
More of the same, and bug fixing. Since I’m still early in development this is a great reminder not to make bugs to begin with!

Stage 9: Profit!
$$$

Categories
Game Development

Going on 10 hours setting up a project with Active X

If you asked me, or any other game programmer, to setup a game project with multiple static libraries divided by component it would take half an hour at at most.

If you had asked me, or any other game programmer that I know of, to do the same thing with ONE Active X / MFC project… well I just finished and it took 10 hours.

The MFC project is like a virus, or a tumor, in the body of the solution. Simply renaming a file can cause a link error. Then you change it back and get some other link error you’ve never seen before. At one point I was trying to change the output directory of the ocx, which somehow caused it to no longer link and the exe launcher to stop running due to some resource conflict. I had to create an entirely new Active X project, copy over all the relevant settings, remake some of the files, and import it into the solution. Although it was identical to the old project it now worked where the other one didn’t.

I’ve gotten into the habit after EVERY change, no matter how meaningless (such as adding a ‘d’ to the end of the output filename in debug), to recompile everything in both debug and release and run it to make sure nothing broke. Sound pointless? I didn’t do it the first 8 hours and I did do it the last 2. That’s the only reason it only wound up taking 10 hours instead of 20 or 30. Of course the few times everything actually runs I also zip it up and keep a backup so I can revert the entire solution, which I had to do several times.

There are so many little annoyances and time wasters. For example, if you make a temporary project, build it, and delete it your registry now has junk in it. The Active X Control Test container has an unregister button but it only works if you still have the same project on your harddrive using the same GUID. It asks you if you want to wipe out the registry keys, but that never works. So every so often I have to manually edit and clean out the registry just because I’m creating test projects in Active X.

Active X Registry Cleaning

Anyway, it seems like I finally got things running:

First working solution

Perforce is being a pain in the ass but I can’t blame it since few people have to delete, create, move, and rename projects as much as I have in the last 10 hours. So I’m just going to wipe the database and upload what I have.

Categories
Game Development

MFC = Garbage ++

MFC is an IMMENSELY buggy and bloated piece of crap. I spent the entire weekend just setting up the damn project for Christ’s sake.

1. Kept getting a crash when quitting an Active X control – it’s a known bug in the compiler and I’m a novice user that encountered it 10 minutes in.
2. Couldn’t compile due to various library conflicts
3. DirectX 8 kept loading some stupid library that was removed for 5 years now. Had to upgrade to DirectX 9
4. Overriding the Run function flat out doesn’t work.
5. The registration utility crashes and fails to consistently remove dead projects.

I’m having these tremendous, undocumented show stoppers time and time again. If you search for the same linker errors they are ALL OVER THE NET.

Of course what I’m doing is very advanced so you can’t blame them for missing a few bugs. In one case you have to:
1. Create a default project
2. Run it

Another is even more complicated:
1. Create a default project
2. Add one line of code that doesn’t do anything
3. Run it.

Assert

Was this even tested? Why does anyone use it?

Categories
Game Development

The value of open source software

When I originally started programming my view of open source was it meant there was more code I had to look at and learn in order to be productive. The implication was that with closed source libraries the author was responsible for creating true black boxes – input goes in, output comes out, and since you had no knowledge of the workings the author should carefully document each function and system. The other half was that open source library authors could be lazy – you were expected to look at the code if you had a problem.

Ironically, I started out using the worst documented and packaged API I’ve ever seen – Panard Vision. This was back in version 4.0 or so, but I checked on the website recently and saw something like “Version 7.0 just released, documentation coming soon.” I was more tolerant and less able back then than I was now, so I spent a good week just trying to get it to compile. You can imagine my rightfully felt wrath, considering I just spent several hundred dollars registering. I wrote a scathing review on the gaming site I was running back then. That was ridiculous since the gaming site had nothing to do with programming libraries. I just wanted a place to attack and vent. Considering how unpopular his library still is, even after all these years, it seems like others agree documentation is important.

Programmers document or not depending on their own conscientiousness and it has nothing to do what they should do. Open source simply lets you see inside the black box if you want to, which you will when you run into bugs. Recent experiences have driven that lesson home.

Closed source libraries protect the author at the cost of the user’s time. Since my time is valuable to me, I’m immediately rejecting libraries that are closed source from this point forward.

Categories
Game Development

How to make an appealing graphics engine

With all the engines I’ve been looking at I thought it would be fun to write down what appeals to me.

In order of importance:
1. Easy to use
2. Encompassing set of tools
3. Doesn’t use script, or if it does the role of script is limited and optional.
4. Feature set

Easy to use
Ease of use is important to me because, like most people, a graphics engine is a means to an end and not an end in itself. I want to get the engine installed as fast as possible, spending as little time as possible learning, and getting the engine to do what I want with a minimum of fuss. This is one thing good about the Wild Tangent engine… once you get past the installation 🙂

Toolset
For much the same reason as ease of use, my goal is not to spend a lot of time writing exporters for custom tools and getting those into my game. My goal is to get the artwork into my game as fast as possible with as little effort as possible. If I have to read 20 pages of text and follow 5 different links to get a model into my game it just isn’t going to happen. Ogre 3D could stand improvement here especially, since the only level format it reads requires a license from ID Software to build. Like I said, it’s not going to happen.

Doesn’t use script
We have a common theme going here. If an engine uses script, that means I have to learn what they did to write it. I don’t want to learn what they did. I don’t care what they did. The last thing I want is to spend a week figuring out an arbitrary language just to see if I like the engine. As I said in the previous blog, script should be for level designers. When it comes to designing my levels AFTER I know I like the engine, fantastic.

Feature set
This is the least important to me. Why? If I wanted a huge feature set then I’d be making a huge game. If I was making a huge game I’d be using a huge engine and would have a huge amount of money to buy said engine. I wouldn’t be using a free engine. I’d use an engine where I know I can get support, where the engine will be updated over time, and where I know it’s been used in successful games before.

Categories
Game Development

Scripting vs. Coding

I’ve been looking at a lot of 3D engines lately for my new game. Some of them rely heavy on scripting, most of them have some scripting, and a few are raw C++. I want to address the pros and cons of scripting, and why one should or should not script.

On the positive end, scripting allows you to design a system that is more flexible and easy to use than coding. With a script system you can abstract away a lot of the heavy or burdensome parts of programming. This is especially true of variable declarations, scoping, and interfaces to both code and data. For example, when I modified the interface in the Torque engine I was able to map the button to an action with one simple line of script. I was even able to put script into the interface engine itself. It wouldn’t have been as easy in a straight C++ implementation and in all probability no attempt would have been made to provide such an interface.

On the negative end, scripting brings with it a learning curve and, unless you base your script on code or well-known tools (C#) you also give up all the tools at your disposal. Both of these are significant. When I had to learn to script in Lua it took me a week to really get productive. While that may not be an issue at work, it is a very significant issue if you make a competitive public engine. Anyone would rather use an engine they can use right away rather than one they have to spend a week learning, especially if that learning is not applicable to anything else. The lack of tools can be far worse, depending on the situation, typically the worse the closer you are to doing programming. FarCry does not use Lua for scripting. It uses it for programming. What happens to the productivity of a programmer when no debugging tools are available? Try writing a program without breakpoints, debug windows, or error messages sometime.

Script should be for level designers. Level designers don’t know how to program. If your level designers can’t figure out how to use your scripts, then you need to hire programmers. If you need to hire programmers, you might as well let them use C++, where they will be the most productive. Otherwise, just like programming without a debugger (i.e. javascript), you’re throwing a lot of effort and money into a hole for no good reason.

The last point I’ll make is on good script design.
Script, properly designed, is designed for level designers to use. Conversely, it should not be designed for programmers. Your script design should, and this is worth saying in bold, assume people are fallible. This means that people make mistakes. If you create variables implicitly, people WILL do this by accident. If you require an obscure syntax, people WILL forget to abide by it. If you use NULL as a valid value, people WILL pass this by accident. Each time these “WILLs” happen, that is wasted time and money down the hole.

Categories
Game Development

First post

Thanks for helping Kraydl!