
| Date | Detail |
|
The final project of the Carnegie Mellon undergrad Game Development course was to work alone or with a partner to create a playable game, adhereing to a pre-set milestone-driven production schedule. I teamed up with fellow Electrical/Computer Engineer Matt Fister and we fairly quickly gravitated towards a top-down shooter as a mechanic that we could build into a finished-feeling deliverable in the 6 weeks we had to work. Inspiration for particular elements came from classic DOS shareware shooters such as Tyrian and Raptor. I had prototyped a bump-shaded sprite system in OpenGL for a previous lab, and we built that in to give the otherwise thoroughly retro game an interesting new graphical touch. We both liked the idea of being able to 'capture' or play as any ship in the game, so I designed a ship and weapon framework that could allow all content to be operated as either a player or enemy (and Matt graciously adapted his AI to suit), and a valuation algorithm to allow anyone who whished to add their own content later and have the game make it appropriately accessible or restricted given its designed power levels. When we couldn't pin down any new world/character concepts for the game, I offered to just spin off my existing Galaxxon series ideas, and Legacy was born. Initial project partitioning had me working on the menus, mechanics, weapons and ships, with Matt handling levels and enemy AI. Necessity also had the project being built simultaneously on Windows- Matt's dev OS of choice, OSX- my own preferred environment, and KDE Linux- the OS run by the cluster the class was officially held and graded in. By the end of the semester, in spite of competition from a grand 3D game built with the full backing of the extracurricular Game Creation Society, a territorial-conquest strategy game with some novel insights in the genre, and a herding game built in the made-for-rapid-prototyping Panda3D environment, among others, Galaxxon Legacy won class vote for best overall game, likely due to the level of detail we had undertaken and the general state of completion of all critical elements. Matt went on happily with a more serious engineering career, and I adopted the Mac side into my own ongoing game portfolio and continued to clean up, revise, and expand it. Early additions included the 'chiptune' sound synthesis engine I'd been working on for some time, plus a selection of new enemies and weapons. I also cleaned and repartitioned the codebase somewhat, revised Matt's 'engine smoke' particle engine to handle a greater variety of uses, and incorporated a number of interface and control suggestions made over multiple beta releases on then-emuscene.com, now macscene.net. Needless to say, with only a PowerPC available to me, the Windows and Linux branches got terminally out-of-sync for most of the later development. |
|
|
When in doubt, consult the internet. When the internet doesn't know, I need to remember to check the bugtracker. http://sourceforge.net/tracker/index.php?func=detail&aid=1258086&group_id=67586&atid=523274 Wrong APIENTRY definition on Cygwin When compiling under Cygwin without _WIN32 defined (to be able to use main() instead of WinMain()) APIENTRY = “” when it should be “__stdcall”. The fix to this problem is to add “ || defined(__CYGWIN__)” to line 81 in “glew.h”. As follows: glew.h:81 #if defined(_WIN32) || defined(__CYGWIN__) This fixed the problem nicely, meaning that apart from some sound lag, the Windows build is feature-exact to the Mac build! Good times. There's always more I wanted to do with Galaxxon Legacy, but under the circumstances (and as ugly as the source has become, or always been), it feels kinda good to officially close the project on a relative high note. |
|
|
After another day of hammering, I got Legacy building in Cygwin, but as I feared, it was linking against X11 libraries rather than native Windows API libraries, and would only run in X11. Which wouldn't be too bad, except it also didn't load over half the textures, had no hope of bumpmapping, and ran incredibly slowly. And required the particular Cygwin-brand X11 server. Not good. So I bit the bullet, grabbed Visual Studio Express C++ and pulled the project into that. The VC++ compiler is a much ornrier beast than g++, and required dumbing down chunks of the codebase before even getting to real compiling issues. Visual Studio was also ornery at building the requisite graphics libraries for the game from source, which I needed to do since all the over-the-counter binary dlls I found were in varying stages of incomplete and generally not targetted to my specific use (the open, standard UNIX general-case). After getting all the various dlls in and set up where Visual Studio could link against them, I very nearly got a build that still had major undefined-function linker errors. So I took a step back, did some research, more properly recompiled libpng, libgfx, and a couple others, and finally had a collection of libraries that covered all the functions I was using. It is at this point that I found out Visual Studio default standard libs/dlls having fatal multiple-definition errors with other Visual Studio default standard libs/dlls is, according to Microsoft, "deliberate behavior," and that when a user's library has fatal multiple-definition conflicts with a Visual Studio standard library (near as I could tell, libgfx made the mistake of trying to #include <fstream> in a perfectly normal manner), the Microsoft recommended fix is to tell the project to completely ignore the user's library. Alternatively, you can set Visual Studio to not auto-include any of its default libraries. That would be fine if large chunks of Visual Studio's standard C++ support wasn't arrived at via said default libraries. And did I mention 'namespace std' doesn't seem to exist in Visual Studio for general use? The fix seems to be including certain standard C++ libraries which themselves set namespace std. It was about at this point that I realized, in addition to the other headaches, all my mucking around in the system32 dlls may have started to break certain core parts of Windows. Happy times. In the renewed recollection that Matt had made the project compile somehow under cygwin/eclipse back at the start, and managed to achieve a Windows-native build, I went back towards that route. I'd already fixed one link-order issue between OpenGL and GLUT, but I went back and made sure I was linking against the proper OpenGL libraries. Which promtly rendered the bulk of OpenGL undefined at link-time. I uninstalled any X11 components that may have been leaving competing OpenGL libraries around, which utterly failed to help, but at least reduced the possible mistake-space later on. Recompiling various libraries so that they would more actively use the Windows API OpenGL libraries rather than anything else, and meticulously checking my #includes no doubt fixed numerous errors... but yielded no progress. I must here give my sincere thanks to André Bleau for repeatedly stating to many users across many mailing lists how precisely to make GLUT work in cygwin, and even providing some well-buried samples within the cygwin documentation hierarchy. After matching every possible non-trivial aspect of his advice and the actually-working GLUT example... I still had almost all of OpenGL coming up as undefined. But I'd at least made my makefile more ledgible. Finally, I tried a little test- pulling GLEW out of a stripped-down version of my basic GLUT framework. Nominal success. It seems adding glew.h (yes, the correct glew.h- I removed all the other possibilities by hand, and rebuilt it multiple times, even making sure it was pointed at the same working OpenGL as the rest of Legacy) spontaneously causes OpenGL to vanish. The GLEW site states GLEW doesn't play well with GLUT unless GLX is present, and it sounds like cygwin only has GLX with X11, so that may be the problem. But Matt did have the bumpmapping working all that time ago, so... Anyway, without GLEW, the rest of the system held together. So I painstakingly adjusted the whole codebase to not try to use any crazy OpenGL extensions if Windows was involved, and the result runs and is stable, if not as shiny as the Mac side. But what can I say? Linux for data, Mac for graphics, Windows for solitaire. The current Windows build is now up by the Mac build in the software section. And if nothing else, this process paves the way for Tekunoma to come to Windows. I may even be able to res RotoNinja if I find good SDL support. |
|
|
With one big project officially in development, and a couple others bouncing around in my head, I'm thinking it's time to finally close development on Legacy in a reasonably formal manner. As one last hurrah, however, I have just pulled all the current source over into Cygwin and, with extensive chewing on both it and my Cygwin environment, finally got the first complete build-error-free binary to come out on Windows in over 2 years. That isn't to say it works. In fact, the executable, near as I can tell, does absolutely nothing. I need to dive into it with gdb and see what I can see. From the sound of the internet, in order to get GLEW and GLUT playing happily together, I may need to build against X11-variant libraries, which would play havoc with compatibility, but may at least let the game run on Windows again. Suffice to say, I have even more reason to hate Windows as a development platform. Okay, okay, I have nothing against a well-established Windows development pipeline properly set up to produce a commercial game. However, building a fresh pipeline from the ground up, with an eye towards open standards and cross-platform codebases and not letting an IDE encapsulate everything into an immediately happy/clean but long-term niche and inflexible bundle (in short making Windows do Unix)... is not the sort of thing Microsoft is interested in, and it shows. Before the project is officially sent into hibernation, I'd also like to get around to a more formal manual. The current packed-in reference sheets have always been a sore point among testers, and I could really use a fresh sample of my writing and illustration capacity in my portfolio. Current ETA on all of this... probably Spring break, in time to present to any companies visiting to cross-check my resume. And if I can iron out a Windows-side pipeline that can correctly handle Legacy, then Tekunoma and any future titles on this quirky but convenient OpenGL 2D framework I've built should see Windows releases more or less in parallel with Mac development. |
| Date | Detail |
|
Some people dream of owning their own studio and making a lot of money. I'd rather be my own studio and have a lot of fun making the games I want to make. Now, that's just not the way the industry works, and I accept that, but for side projects it's still nice to have the ability to do everything myself. Galaxxon Legacy taught me two things: 1) Have a plan and a good code structure before you go in. Galaxxon has a few subclesses, but most of the game infrastructure is one big ugly glob in main.cxx. 2) Assets are a pain. It's not that I don't like doing my own bitwork, or that I don't know Photoshop well enough to do up passable sprites and textures (although the whole bump-mapped sprites thing did make shading more realistic), or that I don't enjoy map design and population. Rather, I found myself putting so much time into the code that I didn't have the energy to crank out another whole level's worth of assets, and after a dozen or so ships and weapons, could only bring myself to make the minimum amount needed to test new mechanic features. Hence, I'd like to explore how much of a game I can make procedurally. A Mystery Dungeon type game is the intuitive starting point, where all levels are supposed to be random and different every play, but I'd like to push the idea as far as I can, with multiple level generation algorithms, procedural texturing, procedural enemies, and possibly even procedural items and music. |
|
|
Finally regained some traction on the project. After far too long, I finally have all the detected equipment types sporting proper grip positions, as well as new "attack" animations. One bigger change anyone who has been following development will notice, however, is the presence of water. Again, all procedural- depth is determined by a simplified Perlin noise function, and the graphics are actually a secondary texture algorithm that operates on previously textured tiles, allowing it to blend the water over whatever is underneath without needing to create a second whole set of meltdown-inducing texture IDs. Finally, I'm trying something new: you've seen me do separate builds, you've seen me do Universal builds, now it's time for a Multiversal distribution. That's right, if you're on an Intel Mac, download this handy zip and run the application. If you're on a PPC Mac, download this very same zip and run the application. If you're on Windows, XP or Vista, you can just grab this suspiciously not-different-looking zip and run... the batch file, which will run the application. But hey, that's what I needed to make you do anyway so the actual EXE would be able to find its requisite data without having every single file kicking around the top-level directory. The upshot of this is that once I'm far enough along to be giving y'n'z save games, one single bundle will give you the same game wherever you take it. Hm... maybe I should try that with Galaxxon... |
|
|
Hot on the heels of the Galaxxon win32 build, I've run Tekunoma through the same Cygwin pipeline, and it seems to be happy. Not much else to say. This build is pretty much in sync with the latest Mac build I've posted. |
|
| Sorry for the lack of progress- my interest got seriously derailed by actively not having any time to devote to the project over winter break, and needing to ramp up for the current semester and pick up all my regular extracurriculars and side projects once I got back. There's a chance I'll do more work over spring break in a couple weeks, but believe it when you see it. Until then, my MacBook Pro is in the shop, so I'm back on my TiBook G4, and I guess as a testament to the groundwork I laid for Galaxxon Legacy, Tekunoma built for PowerPC on the very first try, without any modifications. I went back in and hid some of the unofficial additions since the last posted Intel build and updated the readme. Until I get my MBP back I won't be able to do a Universal app, but there are at least 2 separate apps in this latest archive, and I have renewed hope that a Windows build won't be prohibitively scary (again, once my MBP is back). | |
|
The semester is over, and with it, phase 0 of the Tekunoma project. To close down the academic phase of the project, a brief retrospective: The greater goal of the Tekunoma project (originally "PMD," literally for "Procedural Mystery Dungeon") was to leverage procedural content to create a game with an initial scope that might seem too large for a one-man studio. The academic phase was divided into a series of proof-of-concept milestones, namely 1. Create a procedural map generator. 2. Create and utilize procedural items and sprites. 3. Utilize 1 and 2 in a playable experience. Milestone 1 brought with it some unexpected challenges, such as simply finding a random number generation method that was reproducible and platform-independent, with an eye towards a future multi-platform release. The process of writing a plug-and-play algorithm system also got me off on an unexpected educational tangent exploring function pointers further than I ever had in C++. I was unable to track down any code or theory behind the classic Worms level generator- possibly the holy grail of 2D terrain carving and texturing- but with a combination of tabletop RPG map generation theory and good ol' Yankee ingenuity I managed a couple different algorithms for generally navigable and enjoyable dungeon maps. While I didn't get as advanced as I would have liked, I was also able to come up with believable procedural textures and a little bit of edge refinement which was not strictly on the itinerary even though I generally expected to need both by the end of the semester. Milestone 2 was the broadest and trickiest element. I knew I'd generally need to use a 3D system, likely voxel-based, for defining items in order to extract all the views I'd need for all possible sprites. I also knew I'd need some constraint on the results so I didn't get just a bunch of cubes of binary static or naively condensed irregular lumps. The current system- combine a random length with a random lathe profile and a random radial cut- was random inspiration, but has worked out quite nicely, giving me easy ways to quantify size and shape, and an inherent likelyhood of things shaped like tools and mechanical components. However, simply implementing this system and enough sprite-generation routines to declare that I'd truly done a proof-of-concept took longer than anticipated and bled over somewhat into my Milestone 3 time. Fortunately, Milestone 3 was fundamentally accomplished as soon as I added basic player/sprite code for the purposes of navigating the Milestone 1 maps. This gave me a window at the end of the project to put a little more time into the procedural items and actually turn them into meaningful sprites rather than just arbitrary projections. For the final demonstration, I was able to actually place items randomly within the level maps and make them nominally interactive. This is, however, still short of my original idea of assembling parts into robot sprites and having actual AI characters to navigate the game space. The primary roadblock ended up being the amount of planning and fine-tuning needed to come up with a single ideal projection angle to use for a single frame, let alone the 12 angles needed for all frames of a basic animation sprite set. Ultimately I decided it would be a better use of time to explore more ideas less deeply during the academic phase than to finish any segment in detail. The biggest surprise which may pose a recurring challenge was simply in making OpenGL as hapy as possible while pushing it to do some things most implementations aren't geared towards- repeated dynamic generation and reallocation of textures. Unfortunately, OpenGL is a specification not an actual codebase, and as a result the performance of OpenGL is largely dictated by the interpretations and expectations of the authors of any given implemntation. There are in fact reasonably documented caveats with both the Windows and OSX OpenGL implementations, and the resultant theory is that all textures should be loaded from file up front and never touched again because this is generally how the authors intended the implementations to be used. I have also discovered that there is a very real threshold up to which procedural content doesn't pay off. The time it takes to write and refine a procedural algorithm can be many times more than it would take to generate an asset traditionally. Procedural levels have a high payoff, but procedural sprites may be harder than they're worth until I get the system up to the level of generating the full theoretical combinatoric range of characters and flesh out a grand enough context to make use of arbitrary numbers of them. Ultimately, all the core procedural elements of the game are in place, if pending refinement- maps, textures, items and sprites. This is really what I hoped to get out of the experience. From here, it's just a matter of adding more detail, adding more algorithms to the existing procedural systems, and building the more traditional interface and interaction components which are more of a time sink than a technical challenge. I currently plan to continue work independently, aiming for actual release at some point in the future. The current time to beat, iirc, is 5 years. Working constantly, I could probably finish, with polish, in 6 months, but as Pixel-san no doubt dealt with, I have life and things to get in the way, so I'm not sure what the actual timetable will be. Expect some leaps and bounds in early January while I'm on break, then who knows what as I finish up grad school and find a real job. |
|
|
The semester is almost over, and as such, the academic phase of development is finishing up. As one final hat-trick for the final presentation of the game so far, I took a solid day to write up the dialog system. At some point I'll need to wrap the dialog into a greater event-scripting engine, but getting navigable dialog trees keyed to character portraits was simple enough. If you look closely, you'll notice something interesting about the text relative to Galaxxon Legacy and my various NES demos. The font, at least for now, was ripped from my NES Gray Box demo, but take a close look at, say, the 'i' and the 'w'. With a little evaluation of the byte rasters between loading the font bitmaps and binding the textures, I can now do auto-detected variable width font. I'm also sticking with 16x16 bitmaps even though the characters are, on average, 8x8. This lets me cleanly do characters that break the baseline, such as lowercase 'y', 'p', 'q' and 'j', and opens the possibility of adding oversized characters later for effect. Speaking of oversize characters, you'll notice I'm still using the old Galaxxon font for the debugging HUD. I've generalized my font and string drawing code to manage multiple fonts, and done some preliminary work to embed color/accent codes in the text strings themselves rather than needing to manually set the color before I draw a string. Right now there's only one 'toggle accent' flag character, but with a little more work I should be able to encode arbitrary color changes. And no, don't expect a public build with any plot details any time soon. I'm planning on playing this one close to the vest until the engine is complete enough to do actual alpha/beta test builds. If you're really curious, there are 4 other people who have seen the preliminary intro script in-game, and I may continue to drop hints in comic filler as character and world development progresses. |
|
|
It's been a while, but I wanted to wait until I had another recognizable addition working the way I intended, and ETC project work had me seriously drained last weekend. I'm not up to assembling parts into robots yet, but the new build has an Equipment class able to turn an arbitrary voxel item into an identified and parameterized weapon or shield and generate an appropriate sprite set. Some revisions to the character draw routine layer the equipment in appropriately with the regular sprite components. As a proof of concept, items recognized as "shields" (items evaluated to be generally short front-to-back and much wider radially than they are long) have their own display angle sprites and layering, but the same principle can be used to generate the appropriate views for other recognized equipment types, including but not limited to "hammers," "staves" and "swords." Additionally, I've started some code to randomly scatter items in a level and acknowledge when they're interacted with. This shiny new build has all the tricks of the last one, plus the ability to grab any random item you find to Martha's left or right hand. An item recognized as a "shield", and another small item, equipped and displaying properly from all 4 sides.![]() The same equipment during the walk animation. |
|
|
After nearly breaking my brain a few times, I finally got all the interesting projection angles and then some. I can even do a dirty rotation of the entire voxel mass on one or more axes before projecting a texture. I also wrote a basic pack of 2D manipulation routines to work on the 16x16 tiles used in most of the game. Operations include scaling by half on one or both axes, clean rotation by fixed multiples of 90 and dirty rotation by arbitrary values, translation with or without wraparound, desaturation and single-hue coloration. The next step is assembling the manipulated images into multi-part sprites. |
|
|
The next phase of the project is making procedural items and enemies, which starts with making procedural parts. Over the weekend I managed to implement the base voxel item class which I'll be using for everything. Basically, a random length block is lathed with a random profile and then cut down its axis with a random radially-defined shape. Playing with the parameters should yield most sorts of shapes appropriate for robot bodies, limbs, and wheels, plus various melee weapons and shields. I have project-to-texture code written for the 'easy' 6 directions, as pictured, and I plan to at least get the basic multiples of 45 degrees around any single axis, and compliment those basic views with a series of texture 2D rotation, scaling, composition and color routines to ultimately yield the perhaps hundred total transformations I'll need to generate the required sprite parts. Suitability for a particular purpose can be computed by running various checks on the cutting profiles, cross-sections and total areas/volumes of slices. |
|
|
Again, no visual changes, but I did employ the self-righteous power of terrible horrible ideas to make the random memory-related stalls and premature RAM overloads go away probably mostly except maybe on some machines which might explode faster instead of not exploding at all. New and improved demo is here (old links still have the old build). Be sure to check the updated README. |
|
|
Nothing visually astounding, but I did some major optimization of the edge refining code since it's seriously inner-loop. I also added another action to the caverns algorithm to help it fully connect the map faster. Improvements have been added to the goodie bag linked last post. |
|
|
BIG work done over the weekend. Moving towards getting the actual game engine together, I've now assembled a proper game management class and shifted the level data control over into its domain. I also created the character sprite class which I should be able to use for both predrawn sprites and piecewise procedural characters such as enemies. Galaxxon's layout of using Quadrant I with x-positive right and y-positive up made for some ugly texturing and drawing math even during its own development. For this project, with so many procedural textures based on screen location, and so much needing to be displayed relative to level coordinates ((0,0) in the upper left) as well as screen coordinates, I realized really needed to adjust the camera and FoV to give me a true 320x240 coordinate space a quadrant down. Coordinates are now universally (0,0) in the top left, I just need to invert the y/j values when I give vertex coordinates. Just for fun, I instantiated the main character and wrote the basic level navigation code and a rudimentary level progression. After banging my head against the problem for a while, I finally buckled down and made my pseudorandom generater class a proper encapsulated mechanism with instance-specific state rather than just a pipe through to stdlib random(). Basically, it's now using a file of pregenerated bits and stepping through them based on a provided seed. Not elegant, but it allows me to need potentially as little as one numeric value to completely reproduce a level, meaning I can now not only navigate deeper into a dungeon, but also back out and see the previous floors exactly as they were when I left. I'm still fighting the random uberlag, but it appears to be occuring when neither my CPU nor my memory are maxxed out, and to affect the entire system, so my best guess once again is that I need to track down the appropriate OpenGL clear-the-cache-manually invocation so the graphics card doesn't need to take a few zillion cycles to reprioritize which textures it needs to hang on to. There's also some state that seems to constantly increase as I explore maps, to the point where I can burn out a full 2GB after too much runing around a 40,000-90,000 tile map. I'm not allocating anything new in my code during simple navigation, and I've even run half an hour of constant walking against a wall to make sure that there aren't any odd memory leaks in my animation and movement code, so again I'm guessing this ties back to OpenGL trying to keep some running cache of viewed textures and not knowing when to dump them. Oh, and for those Intel Mac owners out there, an added bonus... |
|
|
And after another two evenings of crunch, finally something looking more like what I was envisioning all along. I've got a few more procedural textures going, all tied to palette inputs so each texture can be rendered with arbitrary color sets. I also used a variant of my caves algorithm to do some edge 'refinement' so cave walls, water bodies, etc. can look more organic. While typing this I think I've had an idea of how to tweak it so it's even more pleasant. |
|
|
No huge news, but I did finish a second level generator, reaching the minimum number of level types I wanted to have to move forwards. To complement my rectilinear rooms and corridors algo from last post, I've worked out a randomly-grown caves algo. Basically, start with a number of seed points proportional to the area of the map, and fill all the tiles but those with solid block. Over multiple iterations (until all seed points are connected by traversable terrain), scan the whole map and clear the solid tiles immediately adjacent to each clear tile with a probability proportional to their distance from the edge of the map (reduces flat-wall-at-edge-of-map syndrome). These images are actually from a slightly earlier version that seeded with a number of points proportional to the average map dimension rather than area (yielded vast open spaces at large map sizes). As a note, I'll probably need to rethink the fully unique texture rendering across the whole map idea. Even with 16x16 textures, there comes a point after a certain amount of exploration at which my system decides to take a minute-long timeout, I'm guessing because the graphics card runs out of room and needs to do a major prioritized purge of all textures that haven't been used recently (which is basically all of the thousands of unique textures it has cached by that point). |
|
|
I've stripped down Galaxxon Legacy, tossed out most of the extraneous stuff and repackaged the useful components into their own classes. I've also decided to drop this project back to an effective 320x240 resolution. GL's 640x480 was nice and classic, to be sure, but didn't end up with the true crunchy retro feel you get from pixels the size of your head. Plus, it means the textures I have to fill in procedurally are smaller and have a higher viewer tolerance for error. I have yet to find any serious in-depth references on, e.g., tabletop RPG map generators or the Worms level algorithm (which would be awesome), but I've worked out a few ideas of my own. The current prototype has a fairly successful rooms-and-corridors generator that works on any map 3x3 tile up to as large as I want to store in memory. I also did a very rough algorithm for procedurally drawing the level blocks. I'll be refining it later, maybe even generating both color and normal maps and using my old lighting hack, but for now it's enough that no two blocks in a level are identical and they're all created at runtime. The only texture files currently in use are the bitmap characters of the old Galaxxon font which I'm using for debugging until I get render algos down for all the various potential dungeon elements. |