In October, I picked up Halo 3, the Orange Box, and Metroid Prime 3. Because it took me a day to get my xbox live stuff sorted out before I could use my new 360 I started Metroid Prime 3 first.
So, I went to Best Buy today to pick up Super Mario Galaxy and they claimed it wasn’t coming out till tomorrow 11/13. So I called Gamestop. They have it. I checked Nintendo’s website it says 11/12. So I give this info to the robots at Best Buy hoping I don’t have to drive across town to get it. Nope, their computer says 11/13 so they are not putting them out on 11/12 even though they have them. I’m curious what the story behind that is. Stupid mix up at Best Buy HQ or some other reason they are not allowed to put it out on release day. Oh well, Best Buy loses my sale. Worse for them, I was going to buy COD4 and the Ratatouille blu-ray but I’ll get them all somewhere else.
You’d think this would be obvious but it’s surprising how often I run into source code that doesn’t use self documenting names. Many developers will use the shortest names possible. I’m sure plenty of my old code is this way. Some of you may have asthetic reasons for short names. I’d argue asthetics should come after logic and practicality. You’re goal should be to write code fast with as few complications and bugs as possible. Code that is easy for others to understand so that they also don’t get confused and run into bugs.
Let me attempt to point out some examples of self documenting names and non-self documenting names and the problems they cause.
void DrawLine(float x, float y, unsigned int color); // <- bad
This looks like a straight forward function except what is color? Is it in the format 0xAARRGGBB or 0xRRGGBBAA or 0xAABBGGRR or maybe something else entirely. Any time wasted looking up what it’s supposed to be is one more reason you’re going to be sitting at your desk late at night instead of out and about.
void DrawLine(float x, float y, unsigned int colorRGBA); // <- better.
Now it’s very clear. Color is 0xRRGGBBAA format so 0xFF0000FF would give you 100% red.
Someone might suggest instead of the type being unsigned int, maybe it should be custom type. That’s fine, just name the type something clear. typedef unsigned int ColorRGBA not typedef unsigned int Color
void DrawLine(float xPixels, float yPixels, unsigned int colorRGBA); // <- best
Ah ha!, x and y are in pixels.
How about this one.
void copy(thing* a, thing* b); // <- bad.
does this copy a->b or b<-a?
void copy(thing* a, const thing* b); // <- better.
That helped beacuse obviously we can’t copy a->b if b is const but assume the copy function is 100 lines long. Maybe it’s copying an array of something and inside there’s something like copyarray(a.m_arrayData, b.m_arrayData). Again, looking at that single line I’d have to go reference the definition of a and b to know which side is the source and which is the dest.
void copy(thing* dst, const things* src); // <- best.
This one obviously we copy src->dst, no parsing the code required. And lines like this copyarray(dst.m_arrayData, src.m_arrayData) inside copy will now be readable without having to reference anything else.
Here’s some others:
float rotationAmount; // <- bad float rotationAmountInRadians; // <- better, we know they are radians float rotationAmountInRadiansPerSecond; // <- best, we know 100% what it is vector3::velocity; // <- bad vector3::velocityInMeters; // <- better vector3::velocityInMetersPerSecond; // <- best void Update(float elapsedTime); // <- bad void Update(float elapsedTimeInSeconds); // <- good, ah, it's in seconds.
I heard one programmer object that time wasn’t always in seconds because sometimes (bullet time) he slowed down the game. That’s pretty much irrelevant though, in his game all calculations are done as though the time passed in is in seconds. It’s good to know the time is in seconds, not in frames or some other unit. Name it!
Note that it’s okay to shorten or abbreviate. Just be consistent MPerSec or InSec or use a prefix secsElapsed, mpersecVelocity. A very good article that also deals with similar issues this Joel’s “Making Wrong Code Look Wrong”
These ideas are not about being a code nazi. They are about being efficient and avoiding bugs. Every one of these has bitten me before. I’ve had to dig through levels of library code to find out which is source and which is dest in a function. I’ve spent hours trying to figure out why something did not appear on screen because I was passing radians when the function in question wanted degrees but because the docs just said “rotation” and because the argument was just called “rotation” it didn’t even cross my mind until hours of tracking down the issue.
Another common excuse some programmer will bring up is because their editor shows the help or function signatures or has other kinds of helpful features that they don’t need to follow these guidelines. That might be true if you’re a one man team. On anything larger other programmers are likely to be using different editors which may or may not bring up the same help. I know that in my current project I use both Visual Studio and Visual Slickedit and neither bring up all our help.
So, help out your fellow programmers and automatically document your code by choosing variable names that make the code easier to understand. If I had followed these rules I’d have had to work less, gone home to be with my girlfriend, or moved on to the next feature instead of wasting time figuring out things or tracking down bugs that could be avoided by simply naming things better.
There a few topics I’ve been wanting to post about for a while but I’ve been putting them off because I wanted to change the software for this site to organize them differently.
For example, Maya tips. I wanted to have a page about Maya tips (I do here) but on my current system, if I add a new tip to that page no headline appears on the front page. There’s no indication that anything was updated.
So, for a couple of years now I’ve wanted to add to my blog software that ability but I’ve finally decided I’m not going to add it. Instead I’ll just post each tip separated and make a new category. That’s the more obvious way to do it.
Python is one of the new weapons of choice at one of my current contracts. I’m a big believer in removing as many chances for error in a project as possible. That means for example where as some teams will have their designers edit an Excel spreadsheet .xls file and then require them to also export to a .csv file for the game, I’d prefer if they just save to .xml at all times.
They lose no features because Excel will save all the data, formatting, formulas etc to XML and Windows will even directly open the .xml files to Excel when double clicked so as far as the user is concerned nothing changes. In fact once they create the file Excel will load and save to .XML so there is no need to remember to save as .XML, it just happens. Automated things like that mean no errors.
When using CSV files there is always the issue that the designer may or may not have remembered to export so they change a value, save the file and forgetting to export they spend a bunch of time trying to figure out why their changes are not showing up in the game. Or, worse, when you save AS CSV in Excel, excel then defaults to saving that file in CSV mode. So, if the designer makes any changes after that and forgets to resave the file specifically in .xls mode then all their changes will be lost. Sure they can reload the .csv file but any formulas, formatting, colors, comments etc will all be lost.
If instead they use XML files then they don’t have to remember the step of saving to CVS. They don’t have to worry about saving back to XLS as well and they never have to worry about losing data since that issue will never come up.
I know some teams that write Excel macros to do this. That’s a huge waste of time. Those macros generally have to be propogated to all their Excel files. Those macros often have to be tweaked for different versions of Excel. It becomes even more of a pain at localization time because the developers don’t usually control the machines of the people editing the files in other countries and macros etc are often disabled. I’ve seen no end of problems dealing with Excel files that had macros in them so no, macros are not the solution.
It’s much simpler just to parse the XML. As you can see below it’s very little code. You can easily add it to your tool pipeline or, looking at the example for reference, just make your game load and parse the XML file directly, at least during development.
Anyway, here is code to read an excel XML file (right click and pick Save Target As).
I tried Pythonifying the code so it’s pretty simple to use. The following are a few simple examples
import excelreader xl = excelreader.ParseExcelXMLFile("someExcelFile.xml") print "Cell B4 in first sheet = ", xl print "Cell G5 in first sheet = ", xl['G5'] print "names of sheets = ", xl.keys() print "Cell A7 in Sheet1 = ", xl['Sheet1'] # assumes there is a sheet called "Sheet1" print "all cells in all sheets" for worksheet in xl: for row in worksheet.keys(): for column in row.keys(): print row, column, worksheet[row][column]
The library also pulls out style info which is useful if you want to know the colors (say for generating corresponding materials in Maya) or the font names and sizes (say for auto-generated localized textures)
print xl.GetCellStyle(7,2) # style info for cell B7 in first sheet print xl.GetCellStyle('D3') # style info for cell D4 in first sheet
I was recently made aware of something really great. A version of the C++ Standard Template Library that has been modified and redesigned to deal with the issues of game development. It was created by EA and is called the EASTL (Electronic Arts Standard Template Library)
Dear Electronic Arts,
Please make the EASTL open source with a BSD style license. You’d be doing the game industry and the software industry at large a HUGE public service. You’d be our heros!
I know that on the one hand you’ve put lots of work into it. You might even see it as a competitive advantage so you might be asking why open source it?
Wow! My cell phone has 128meg of ram. I guess it doesn’t have 4 processors. It’s hard to imagine that something so cool as a Cray-XMP only has a fraction of the processing power of first gen XBox (a 700mhz Pentium).
So I finally finished Twilight Princess. I only actually play around 3 games a year. Last November I played Gears of War and since then this is the first game I’ve played. (looking at a demo does not count) I fully enjoyed it, I love the Zelda series but, in the end I thought it was one of the weaker Zeldas. I’d probably rank them
- Ocarina Of Time (N64)
- Wind Waker (GC)
- Link to the Past (SNES)
- Links Awakening (GB)
- Majora’s Mask (N64)
- Twilight Princess (Wii/GC)
- The Legend of Zelda (NES)
I didn’t really get into any of the others like 4 Swords or The Minish Cap or Oracle of Ages / Oracle of Seasons
I’m working on some game libraries, tools and utilties. The first thing I’m posting is some debugging libraries. Stuff I use while making a game, specifically a console game.
There’s 4 major parts to it
- a debug console.
This is just the ability to do a printf to the display. Most development systems let you print to a terminal or inside the debugger. The problem with those systems is the artist, the desginer or myself is not looking at the debugger. We are looking at the game. Therefore, important messages need to be displayed in the game or they will go un-noticed.
On top of that, games generally erase and re-draw the entire screen every frame so some method of re-drawing the messages needs to be created. Without a system like this that process can get quite cumbersome.
The systmem supports output in different colors as well as flashing output to make very important messages stand out.
- print to the debug terminal
Most dev systems have an OutputDebugString type of way to get a message to the terminal. These are just wrappers that provide more functionalty like printf and so I have one place to fix if I switch engines.
- print to the screen
Again, most systems have a DrawText function that will draw a string. I just always need wrappers so I can do printf style formatting and again, I want it in one place so if I switch engines I don’t have to learn a new api or change other code to use a new api.
- debug menus
This is the biggest part. These are menus, controllable from the joypad/controller that you can pull up in the game to inspect and or edit things in realtime.
For all of these my #1 goal was to make something easy to use. So for example there is no need to init any of them. While you can set a few parameters they will work without any settings. The menus and the console only require 1 function to be called for them to operate, etc…
The menus in particular have been designed to be easy to add items to with lots of default handlers. In one line you can add menus that edit bools, ints, floats, either directly or can edit them through functions or even member functions. Menus that call callbacks in C style, CPP function object style and member function style.
They handle enums, although you need to supply a value-label table. They can also handle STL collections and display them as menu items.
Some other features.
- They handle menus that have too many items to fit on the screen and will let the user scroll through them.
- They support non-uniform height menu items.
- They handle the menus cascacding past the right edge of the screen
- They are semi draw order independent.
Originally when a submenu cascaded into the right edge of the screen I would just move it flush right. I assumed since a menu’s parent was drawn before itself I thought the children would draw over their parents and therefore be usable. Unfortunately when I tried it out it became clear that in the engine I was using it in, draw order was not preserved. Text draws and rectangle draws were queued separately. So, I changed the menus to figure out what the right most edge they need is and then I push everything else to the left. Now the draw order doesn’t matter as much since nothing ever overlaps. Rectangles still need to be either drawn before text or with a lower Z order but that’s not the responsibility of these routines.
They are platform independent.
There is a file debugplatform.h that defines a few functions. You create your own debugplatform.cpp and provide those few stubbs and the all these debug systems will start working.
Anyway, I have no idea if anyone other than me will find these useful. I know that many teams are using systems that have other ways to accomplish this kind of thing. For me though I have found them useful and so have the teams I’ve been on. It’s my hope that now that I have my own I’ll never have to write them again.
If you are interested you can find them on sourceforge here. They are released under the NewBSD license so use them how ever you want. There are not a lot of docs yet but the code is pretty well commented. There’s also a file called debugmenus_examples.cpp that shows how to setup a bunch of different kinds of menus. And, there’s a Win32 sample as well to actually see them run. To keep it simple the sample uses the keyboard to emulate a joypad. The cursor keys are the DPAD. The space bar is the Action button if you want to call it that. Think X on the PS3 or A on the 360. Backspace is the cancel button.
At the time I did some analysis of the NPD sales data for games in the USA. The results were interesting. First of all I removed sports. Pretty much universally sports require a license. There are so few exceptions as to not be worth mentioning. At the same time, if you are not making a sports game then the fact that sports games require licenses (cars, teams, logos) has nothing to do with a non-sports game so it’s not useful to include those in the same analysis IMO.