Let’s talk about games and, more to the point, the making of games. I’m going to start a weekly column (here!) sometime next week entitled “Mechanics” where I’ll do my gamer/designer thing by choosing a game that I’ve been playing recently and analyzing a certain mechanic or set of mechanics that, I think, are remarkable in some fashion. But that’s next week.
Microsoft did this really rad thing when they released the XNA Game Studio a couple years ago as a means of giving hobby game developers a means of creating games with a toolkit/API specifically designed for hobbyists that were interested in creating games. This isn’t the first time the company has done something like this, as DirectX fills a similar sort of need, but with XNA Microsoft decided to step up their game. So to speak. XNA is best described as the marriage of the higher-level aspects of DirectX, Microsoft’s own C# (a managed language), and the benefits of both the PC platform and the Xbox 360. The end result is a vastly more approachable environment for game development without a lot of the limitations of setups like Blitz Basic and pygame without overloading the less programmaticly inclined wannabe-game developers that may get scared off by the concept of working with C/C++ and DirectX or OpenGL.
With the original release of XNA almost two years old that is all old news; XNA 3.0 is currently in beta and will launch with an Xbox 360 XNA game browser capable of displaying and delivering XNA games made by the hobbyist/independent game developer community to the Xbox 360 owning masses in a Youtube-like fashion. That’s the idea, anyway. When I submitted my first XNA game I apparently crashed the console of the person who was reviewing my submission. I, apparently, failed to package the game correctly or something. Either way, my first game, which I’ll talk more about in a moment, was far from being up to snuff for any sort of widespread public release so the peer reviewer was probably just doing me a favor. The point is that XNA allows game developers to deploy games to the Xbox 360 with an only an absurdly trivial process required to setup the PC/Xbox 360 XNA game compatability. As far as building a copy of the source code for deployment to the Xbox 360? Well, once the XNA Game Studio executable has been installed and setup the only action required by a user is to right-click a project and select “Create Copy of Project for Xbox 360 [or Zune].” The first time I was able to see my game on my 360 it was exciting, to say the least — though, to say the honest answer, the first time I saw my game on my 360 I realized that I didn’t setup a way to deal with the interface without access to a mouse. Nor did I map a button for escaping the program. These realizations are all part of the experience.
That game I made was the first full game I’ve ever made. I called it Asplode! which, along with my current game Cubegasm, make for some very awkward conversations of the “Uh. What was the name?” and “I didn’t catch that” variety, but that’s neither here nor there. Coming from a C/C++ background with absolutely no thought paid to the concept of actually learning C# before utilizing it for a full game yielded some very awkward optimizations when describing my project to new people. Despite the many faults that Asplode! had it was a lot of fun for me to work on and, more to the point, it was the kind of learning project I needed to get my codebase the kickstart it needed for an actual 3D game project.
The lack of familiarity with C# is one of the reasons I’m writing this: with the release of XNA 3.0 due in the next few months, there is one very important thing that any XNA game developer needs to understand: memory management is necessary even within the confines of a managed language. The primary difference between working in a language like C/C++ and C# is that, in C/C++, memory is managed very carefully by the programmers and the task is, more or less, given to a developer whether he/she likes it or not. C#, however, cozies up to new programmers and holds their hands while all sorts of terrible code is written that may not rear its ugly head until the worst possible moment (end of the project). C# has an automatic garbage collector that, as the name implies, cleans up loose objects when they go out of scope/use. On the PC, the garbage collector is generational and can perform different types of collections ranging from gen0 (fastest; performed on simple object types with no finalizers) to gen2 (a full collection that actually halts the execution of a program). This is important to keep in mind for XNA game development for the PC platform but, on the Xbox 360, the garbage collector issues become more pronounced as the 360 GC isn’t generational so when it fires it actually has to pause all of the currently running threads while it does its thing.
This brings me to the impetus for writing this little introduction to a two-year-old system. For Cubegasm, my current action/RTS, I need vastly more complicated methods of handling rendering, updating, and then collision detection (along with a basics physics simulation layer). Now, I’m no good at physics nor am I a prodigy when it comes to the kind of calculus that is saved for a third- or fourth-semester college class but, due to the infancy of XNA as a community there isn’t an abundance of “middleware” that exist for C/C++ applications. When I was interested in integrating a physics solution into my game I heard good things about Bullet and, subsequently, BulletX but when I actually tried it in my project I discovered that it fired off the garbage collector every two seconds or so (down from the two times immediately after initialization that I had my game firing it at). So, as an aspiring game developer that wants to write his/her own program from scratch here’s what I’m going to recommend: think carefully about your game design. Ambitious is great, I encourage it, but no one ever got anywhere by being overly ambitious about a game project that, eventually, disheartened everyone involved with it to the point that it gets cancelled. And, if your target platform is the Xbox 360, then remember that your game isn’t going to be running on the latest greatest PC hardware but, rather, the hardware that is within every Xbox 360. What runs great on the PC is almost certainly going to run much slower on the Xbox 360 due to less powerful hardware, memory restrictions, developer assumptions about the system, and so on.
Now for a list of communities/blogs that will almost certainly prove invaluable:
In the end, remember: if you use XNA then you, despite being the kind of developer that has no publisher backing, money source, or the kind of time/manpower that full studios have, have the ability to develop a game for a goddamn console. Just think about how cool that is.
For the interested, along with the release of Asplode! I packaged up the project source code because I thought that it may prove useful or interesting to someone. It’s not incredibly well-organized or commented but I’m still using some of it for Cubegasm so it can’t be all bad.
For this update, my role in Asplode! was absolutely minimal. While I’m in the middle of a mild crunch for The Political Machine 2008 and then away at Rochester, New York for a Paramore concert, Josh was working asininely hard on version 1.2 of Asplode!. As started, my role in this update was purely peripheral as, in my spare time, I’ve been working on the start for Bipolar and taking some of Josh’s code for his game and turning it into a more generic library that both of us can use in our current and future projects (the library is HardCat Library, obviously). Anyway, major changes:
For some inexplicable reason, the XNA redistributable may still fail to install using the installer, so you may want to manually install it: XNA redistributable.
On Sunday, I linked to the source/executable for my top-down, arena space shooter Asplode! and one of the things I wasn’t really proud of was how terrible the performance was for the game. Well, one of my friends took the burden of fixing it up a bit and made an installer. He then passed all of this new fangled technology onto me and, in return, I edited a couple more of the source files, added him to the game’s credits, and made a new, updated installer for the game. So here, ladies and gentlemen, is a far more proper release of the game.
This installer will execute the DirectX Web Setup, install the .NET 2.0 Framework if it isn’t already, and the XNA redistributable, but it does not contain the source for the game. Like any XNA game, this will require Windows XP or Vista, and, at the very least, a graphics card capable of Pixel Shader 2.0.
Yeah, so, I’m releasing Asplode! now and such. And, along with the game, comes all of the source to the game.
I originally wasn’t planning on releasing the source but as development winded down and I started to play the game for longer sessions I soon realized that the game became virtually unplayable on my machine after about seven-eight minutes. I thought this may have been a result of poorly-managed graphical assets so I took a couple days to optimize them (and, as a result, the VectorModel and VectorParticleSystem bits of the code are an absolute mess to comprehend). After I finished doing that I jumped back into the game and, while it ran better for a while, the horrific mid-to-end game performance was still very much a factor. I went through and tweaked and optimized bits of code in other places that seemed like they would cause issues and, still, the performance problems persisted. At that point I decided that, since I got the game to a playable state and I didn’t want to devote a whole lot of time to what is, essentially, a Geometry Wars clone, that I would just throw a main menu screen on the thing, an end-game screen, and release the source code and call it a day.
So that’s what I’m doing. Here’s the game; tremendous performance issues and all.
The Game: Asplode! plays out pretty much like you’d expect; on the 360 controller the left joystick handles movement and the right joystick aims/fires bullets. There is a score multiplier which is slowly increased with every kill made up to and the multiplier reaches a maximum of nine; every time a player dies, the multiplier is reset. There are also three possible weapon upgrades. (which persist after death) which are awarded based on the number of asplosion combos — any death with a red pentabomb involved. A player has only three lives; I thought about implementing a way for a player to earn more lives but, since I have no life, the least I could do is minimize the amount of life a player can have. So there’s three. That’s it.
The Source: Uh. Yeah. Just try not to learn anything aside from what never to replicate. Ever.
The Requirements: One of the issues with an XNA title is that there are a few necessary items to install to get one running. So, I’m sorry about that. If it wasn’t such a beautiful creation, I wouldn’t use it. XNA Redistributable (Included), .NET 2.0 Framework, and I believe a run of the DirectX Web Setup and/or Visual Studio SP1 Redists if the first two don’t get the job done.
I’ve been playing a very time-intensive game of musical chairs with various three-dee engines over the course of the last two-and-a-half weeks in an attempt to find the one that would be best suited to my particular development style and the kind of game I want to create. And I can safely say that, tonight, I have reached the ultimate solution. That’s right, after toying around with things like TorqueX, Torque Game Engine Advanced, OGRE, Irrlicht, Nebula3, and, finally, PowerRender. The latter two of the list appeared to have the most potential, with PowerRender being the closest thing to what I was looking for, but the most recent iteration of the engine is still under heavy development and, what was the most troublesome, seems to be getting very infrequent updates. So, after all of the wasted time, I decided that I was going to dig out my old C++/D3D9/D3D10 framework and just rip out the D3D9 parts for use in a new framework which I could use in the future.
I got exactly an hour-and-a-half of work done on that last night before I realized that it felt way too much like the kind of engine work I do at my job every weekday. So now, and for realsies, I’m back with XNA. I’ll be releasing Asplode! this weekend in its terribly-performing state (and open source) and, hopefully, everything I learned in the development of that will help me create a far more useful toolset this time around as far as memory management is concerned. The most important lesson I have with me that I learned from Asplode! is that the most important thing about memory within a managed environment isn’t necessarily the allocation of memory so much as it is the deleting of it. Apparently the garbage collector is a wicked beast that must be appeased in order to maintain stable gameplay performance. I don’t know. I’m still getting the hang of the intricacies of C#. When I was working on Asplode! — and this will be readily apparent in the source if people peruse it — I didn’t know anything about C#. I simply coded as if I would code a game using C++ and, when code didn’t compile, I read up on why the error occurred and what I needed to do/learn in order to fix it. Hopefully, this time around, I’m a bit more well-prepared. It also helps that Drilian and I are teaming up for some of the more game-independent stuff.
As a random note, I beat Final Fantasy 7: Crisis Core earlier this week. While I have the same issues with it that I do most RPGs (that the combat becomes asininely annoying by the end of the game), the game did the Final Fantasy 7 universe — and FF7 is the only JRPG I’ve ever enjoyed (and loved) — absolute justice. The story was incredible and provided a lot of great depth on Zack, the inner workings of SOLDIER, and the root for Cloud’s identity disorder. And seeing Sephiroth function in more “normal” times and take actual solace in communication with friends/peers was cool. I’m just waiting for my copy of Advent Children to arrive so I can re-watch that. Now it’s back to Wipeout Pulse, AoE3: The Asian Dynasties, and more Rock Band. And GT5: Prologue. Grand Theft Auto 4 can come out anytime now as well.
Anyway, yeah, that’s about it. I hope everybody has been The Daily GameDev.net news pieces I’ve been posting every weekday morning. They’re almost asininely fun to write up but they do tend to take the place of dev journal updates at times, so if this thing has become a bit more stagnant than usual then that’s probably the reason.
At this point, I think that it’s fairly safe to say that the meat of Asplode! is finished. All of the primary gameplay is in place, the enemies are all implemented and handled in a state that I’m fond of, and the player controls, responses, and such are all implemented. At this point any more features that I add to the gameplay portion of the game are either polish points or experimental ideas that I may or may not keep as part of the game (a few automatic weapon upgrades, various ideas as to how to handle the score multipliers, and whether or not I’ll allow the player to acquire more ships/lives as the game progresses or not). I mean, I still have to add the main menu, restarting/quitting mid-game, and handling option changes dynamically instead of by text file and such, but unless there’s something I’m vastly underestimating about this process (I’m not having a fancy UI or anything), it shouldn’t take more than two more weeks — as I’ll be gone all next weekend.
That all said, what I’m struggling the most with right is performance. The game runs smooth and excellently for the first two-three minutes but, shortly after the two-hundred second mark, it started chugging something fierce. My first response earlier this week was that it was, obviously, the particle system and its insanely inefficient rendering method where I filled a vertex buffer per-system and then rendered the contents (per-system). I remedied this by batching all of the particle geometry together into a single write-only vertex array/buffer indexed by a static index buffer and rendered all of the contents in a single draw call. The number of particles doesn’t generally spill over into a second batch but, even as a worst-case scenario, that’s two draw calls total for that. Pictures from that experiment (this actually went really well and I only had one screw-up):
That improved the overall framerate a decent amount but it still was, clearly, not the main problem. The only other huge graphical culprit that could have been causing a problem were the vector model rendering routines. When I started looking over the source code I realized that these were the first things I wrote when I switched back to XNA after my D3D10 experiments and the code was absolutely atrocious. I had two draw calls per every model and, on top of that, I was generating data for each of the models from the source XML data whenever a new enemy was created. So, not only was I reading and parsing the XML data but I was generating all the geometry from the minimal data in the XML. It took most of Saturday to sort out all of that and batch the model rendering routines together and, in the process, I made a number of pretty-looking screw-ups:
I’m officially declaring the game in beta testing status as of now and here are some screenshots from a playthrough an hour or so ago.
Not that I spent recent nights playing stuff like Army of Two, Mystery Dungeon: Shiren the Wanderer, Company of Heroes, Master of Magic, Supreme Commander: Forged Alliance, Bully, Ratchet & Clank, Geometry Wars, Everyday Shooter, Advance Wars: Days of Ruin, or God of War: Chains of Olympus instead of actually updating my dev journal or anything… But, yeah. Pretty much did exactly that. I’ve still gotten a bit done on Asplode! every night but, by this point, I’m mostly making various optimizations wherever I can to support the ludicrous amount of enemies and their assorted particle effects on screen in the mid-to-late game. Here’s a screenshot dump of shots that would have been attached to journal entries if I wasn’t playing so many games lately: