Tag Archives: porting

Missions of the Reliant: Happy Belated Anniversary, Reliant!

The one-year anniversary of the project to port Missions to modern Mac OS was one week and 5 days ago. I’m sorry I missed it, but as always, life puts a heck of a damper on the fun we want to be having. Still, I’ve got a few extra minutes to spend on it, and in the last few months I’ve learned a lot of new things. One of them is that having a plan is almost always a good idea! So as gift and apology, here’s the plan for the present and future of Missions of the Reliant!

  1. Because I haven’t worked on the project in a while, and because the time I’ve spent in iOS has taught me a great deal about proper Cocoa programming and OpenGL, my first action in returning to the Xcode project titled “Missions” will be to go through the game’s subsystems and fix some of the rather basic mistakes I made as a less experienced coder. This includes such things as the use of VBOs in OGL, unification of the disparate “node” classes into a proper hierarchy (eliminates an amazing amount of duplicated code), replacement of some of the things I hand-crafted (such as audio file access) with third-party libraries (since the ones I’ve investigated invariably did better at what they were meant for than my efforts), and possibly an even more general refactoring if I decide it’s necessary (a decision which pends further review).
  2. After that comes completion of the missing gameplay functionality. I don’t at this moment have a decent list of what’s missing available, but the stuff that comes to mind are most of the computer functions and the enemy AIs. Once all of that is done, the lot of it has to be tested to make sure I didn’t miss anything above the level of fine details. This leads up to…
  3. … The storyline, the literal “missions” of the Reliant! Those of you who played the original game (almost all of you, I’m sure) will remember that Mike provided three of them – invasion, rebellion, and time travel. These require tying together all of the gameplay elements in their proper linear fashion, which may sound simple, but this is one place where the mass of spaghetti in the original source code isn’t nearly so sad to look at (with, as always, apologies to Mike), because that was the only way to do it without OO features at least as advanced as Objective-C’s.
  4. At that point, the game will be ready for beta testing, and a 1.0 release. Said release will of course be freeware, and I plan to distribute through the App Store as well as on my Web site. I plan to ask Mike for suggestions on how to handle beta testing, but I tentatively plan to open it up to, at the very least, to everyone who subscribed to the mailing list.
  5. With 1.0 behind us, there will still be plenty to do. The game in that state will not be a direct port, and just won’t provide the sense of nostalgia I suspect many of you are, like me, hoping for. There are too many new features and changes in the interface. Some of them were my creativity getting the better of me, some were just inevitable moving between two completely different operating systems and programming languages across a gap of more than a decade. I plan to make a 1.5 (or whatever!) release which provides a “classic gameplay” mode, wiping out all the new features and restoring as close to the original exact interface behavior as possible. User feedback may, of course, convince me that this would not be worth the effort, but that’s something to think about at the time, not now.
  6. Finally, I never saw Missions as a static game. Mike released it as such because, among other things, that was the only kind of game we had back in those days. But just like Kirk and the Enterprise had lots more adventures after the original series, so can this game have more episodes. My vision is of downloadable content, and even a scripting interface so anyone can make new episodes for the game. This is a project almost as large as the game itself, and is another thing to possibly set aside based on the feedback of players, but it’s something I would certainly enjoy doing.
  7. Even further in the future, perhaps a 3D engine and models? The sky’s the limit! But let’s not get ahead of ourselves. At that point we’re talking about an entirely new game, practically an MMO if one takes the thought far enough, and that’s pretty silly if you look at it from right now. It might not be later!

I hope it’s obvious that I’ve put some thought into all of this. I still won’t have a lot of time to work on the game, but any is more than the none I’ve had lately, so expect to see updates coming again.

As always, my deepest thanks go out to you all for your patience as I’ve struggled my way through this project, and I’ll continue to do my best not to disappoint.

P.S.: I have considered making the game require Snow Leopard to play. It’s been long enough since its release that this might not be a bottleneck to most people, and it would considerably simplify some of the code; Apple added quite a few nice things to Cocoa only that recently. Please leave some feedback on this thought in the comments or on the mailing list!

Missions of the Reliant: He’s dead, Jim.

With heartfelt apologies to DeForest Kelley.

The doctor is now a useful officer. Good luck getting the last word, though. Wounded crew get treated with the very latest technology, the skill of the best surgeons in all the Alliance, and often a grumpy bedside manner well worthy of Robert Picardo. I wish I could make a Doctor Who reference as well, but I know I could never do justice to a series I’ve only seen a tiny slice of.

Aside from the working doctor, I fixed a long list of minor bugs, things like the engineer doing repairs at the wrong speed, wrong text colors in the console, weapons and helm commands not requiring skill from the officers, and so forth. Stay tuned for more!

Missions of the Reliant: How many times do I have to tell you, the right tool for the right job!

Here are some highlights of my latest progress:

  • The engineer now has something to do. Systems can be repaired at a speed relative to the officer’s engineering skill.
  • When systems are damaged, the appropriate officer tells you so.
  • I fixed a really annoying problem with key presses repeating so fast it was very easy to give incorrect commands.
  • I finally realized I had to manually adjust the texture width for kerning for strings drawn in Geneva.

The doctor is next. I’m pondering an easter egg that would change the name of the officer to David Tennant. Squee.

Missions of the Reliant: Receiving subspace message from Alliance HQ

According to my commit log, I’ve accomplished a lot, but I think a lot of that is stuff I’d already done and mentioned here, and just not committed. Bad programmer! Bad! No treat for you! Anyway, there is one thing I know hasn’t hit the blog yet, and that’s incoming subspace transmissions. Those are the big blobs of text in the middle of the screen containing all that awesome plotline Mike wrote. Nice stuff, if you ask me. Those work now, and they come in correctly via the helmsman, using the reports interface and everything. Only part that isn’t quite right yet is there’s no HQ text flashing at the corner of the viewscreen, but that’s easily done. I’m inching ever so slightly closer to having a fully implemented mission here.

Things still missing to make Assault on the Alliance completely functional:

  • Engineer functionality (repairing damaged systems)
  • Doctor functionality (healing wounded crew)
  • Starbase interaction (don’t actually need all of it to make the mission work, though it won’t be as much fun without a Mat-Trans or crew swapping)
  • Cruiser and battleship AIs (actually less complicated than the fighters)

That’s all! Stay tuned for more progress!

Missions of the Reliant: Thanks for the support!

I don’t have any real progress to report, with one exception: The “Report” command for all crew members, the one which tells you that systems are damaged and that crew members are hurt and that messages are incoming and all that sort of thing, is now complete and working. It’s not tested past the most basic stuff yet, though, so give me time :-).

The real thought behind this post is to thank you all for the unremitting support you’ve all shown these past months as I’ve worked on the game. Every few posts I get a whole list of comments from everyone who says they’ll wait for me to finish it, telling me how much they look forward to the results of the work I’ve put in. I just wanted to say, I truly appreciate it, and I’m certain I wouldn’t have gotten even this far without that to encourage me. Thanks, everyone :-).

And, as always, a special thanks to Michael Rubin; without the enthusiasm he showed when I first approached him with this idea, it couldn’t have happened.

As a gesture of my appreciation, here’s a short QuickTime clip of the Reliant entering warp drive. I’ve been promising you a real look at this thing for a long time. Enjoy! And please blame CoreText and QuickTime for the text layout and sound synch problems! ;-)

QuickTime Player plugin required. Tested on Firefox 3.6 and Safari 5.0. No guarantees about other browsers.

As always, stay tuned!

Missions of the Reliant: Take the weapons station

Well, I cleaned up the command console code quite a huge bit, it now works quite nicely, and also the gunner’s commands are all fully implemented (with the exception of, as with the helmsman, “Report”). I wish I had more progress to report, but I’m still here and I’m still working on the game, so hopefully you won’t lose hope yet.

This project has taken quite a bit longer than I ever expected, I have to admit. I started back in February with the impression that it would be a simple port, but I forgot at the time that I hadn’t yet learned much about OpenGL, OpenAL, and other such things. It’s turned into a tremendous learning experience for me, in everything from subsystems and frameworks to code design and testing procedures. Then real life came and intervened, kicking my progress down to an even slower crawl. That all being said, I’ve been enjoying it all the way through, even when OpenGL and CoreGraphics have been violently frustrating me with the problems of text rendering on a CGL surface :-).

I hope to have a more substantial update this weekend. Wish me luck! As always, my thanks to Michael Rubin for giving me the chance to work at this, even if I have taken just this side of forever ;-)

Missions of the Reliant: Status update

It’s been awhile since I’ve updated, and I thank anyone who had the patience to wait around to read this post! To all of you, I apologize for the long hiatus.

While I’m still working on Missions of the Reliant actively, it is not at this time my highest priority. As always, the needs of reality interfere; as Missions is not a project I expect to be making money from, I can not unfortunately prioritize it above projects I do expect to be paid for, as much as I might like to. For this reason, I’m afraid I must, with apologies, beg the patience of all of you as work continues on the game at a slower pace.

All that being said, there has been some progress. The command console, that little window where you interact with crew and the computer, is now completely working and looks correct at last! All but two of the helm commands are implmented, and those two are missing only because I haven’t built the functionality for crew reports and subspace messages in yet. My plan is to implement the commands for the weapons officer, engineer, and doctor next, in that order. The latter two automatically bring the functionality of system repairs and treatment of downed crew members, filling in two more gaps in the functioning of the Reliant as a whole.

From there, it’s just a matter of the battleship and cruiser AIs and a bit of game logic to manage their spawning, and the first mission is essentially done.

Once again, thanks to everyone for your patience and support!

Missions of the Reliant: You’ve got to know why things work on a starship.

I finally worked out the major design issues blocking the way for the command input console (also known as that tiny rectangle in the bottom right you see short messages and crew commands in) to exist. Long story short, a lot of things were being handled by the player object and the crew objects that should’ve been handled in the command console class (which didn’t exist yet). Took a bit of retooling to put everything where it belonged.

The console and computer (which I had to implement at the same time since the console depends on it being an addressable input processor) are far from finished products, to be sure. The console pretty much doesn’t work (though it does display not responding when a crew member is down), and the computer is just a framework of code so the console can operate. There really was no way to implement either one separately at this point, since the console depends on the computer and the computer has no function at all without the console. However, at this point I’ll be focusing on the console and adding the computer later, since finishing the computer involves also implementing a number of thus-far ignored displays (such as the galactic map, the ship mods and cargo screens, and the library screens), whereas finishing the console brings back functionality that was partially working before and isn’t now.

A lesson to take away from some of the snafus I’ve made during this project is to have clearly defined rules of interaction between objects early on, and to stick to them. The “responder” class which defines common functionality for anything that needs setup/teardown, mouse/key input, periodic tasking, and access to (pseudo-)global objects does not define any way of letting subclasses say “these objects here need to know about any input I don’t handle and need to be tasked when I’m tasked”, for example (and there’s no larger list of responders to iterate over), which has resulted in a number of subclasses each doing it a bit differently. It works, but it’s ugly as heck. (For the curious, the main game controller prods several top-level objects from its own responder methods, each of which tick others that they’re responsible for; it’s a mess.) I need to go back and standardize and commonalize this stuff. Why didn’t I do that before? At the time I never realized so many different objects were going to need to respond commonly to those inputs, because I hadn’t known then about all the design necessities that I do now. There just weren’t enough objects then to make it worth managing responders the way Cocoa does with NSResponder (first, previous, and next responders in a chain). Now there are.

Who knows. Maybe a certain five-digit prefix code will become an easter egg that does something interesting.

Missions of the Reliant: Why the bridge is an easy target at the top of the saucer section is something I never understood.

I’ll give you this one, Star Trek fans. It’s a shortening of a quote from the Captain’s Table series of books, specifically book five, “Once Burned”, by Peter David: “Why in God’s name the bridge, arguably the most important strategic point of the vessel, is an easy target at the top of the saucer section is something I never completely understood. Why not just paint a big target on your ship and write, ‘Aim here for best shot at the captain’?” – M’k’n’zy of Calhoun, inner monologue.

Straegic design choices have never been shown to be a strength of the human race. Take, for example, this ever-lengthening thread on Apple’s objc-language mailing list, which can be summarized as an increasingly complicated debate on the merits of the design of the C language. What it really boils down to, though, is two important points:

  1. Designers of any sort, linguistic or otherwise, do not have the power to see into the future.
  2. Users of any sort will cling to the old and proven over the new and possibly better 99 times out of 100.

This is a problem I’ve run into in Missions. My code design as it currently stands has no real place for me to implement the code necessary for handling all the different screens of commands and text necessary to implement crew and computer interaction. Right now, I’d have to duplicate a lot of interface code in two (possibly three) separate places, and unifying it would mean exposing implementation details across two subsystems. True, Mike’s original code exposed everything to everything with global variables, and that’s a legitimate approach for games, but I know it’s not necessary in this code if I take the time to go back and redo some of the code structure correctly. Also, it offends my sense of object-oriented design; I worry that it’ll open me to further trouble later on.

Anyway, the practical upshot of all this is that it’s going to take me a while to do something I should have dealt with much sooner. Refactoring, even across only a minor subset of a code base, is a significant pain. I’ll try to keep tabs on my progress here, but if I don’t post for a week, don’t worry, it just means I’m still working.

Missions of the Reliant: We have high hopes that this will, if successful, generate power to keep us alive

The viewscreen “system” is implemented, or more exactly the source code needed to do more interesting things with it is in place. It can’t currently take damage or go offline, so there’s no functional change. It’s a bit of code work that needed doing for the sake of correctness and to ease later improvements.

Life support is now implemented and functional, and damage to it will make crew members start going down.

Computer is next, which means crew interaction is next. Long overdue!

Missions of the Reliant: Scanning. Indications negative at this time.

Today’s list of completed tasks:

  1. Made the torpedos work the old way. You’d think that was simple, but nope…
  2. Implemented long range scanners as a ship’s system (can take damage and go offline, can be repaired, code isn’t special-cased anymore)
  3. Implemented sector scanners similarly
  4. Fixed a long-standing issue with the way explosions were being handled so that they finally look exactly correct.
  5. Fixed a nasty memory leak with torpedos that was spewing errors to the console.
  6. Fixed a pair of cosmetic bugs with the damage indicators at the bottom of the viewscreen (specifically, the impulse drive’s indicator wouldn’t flash, and the indicators for the torpedo launchers were missing).
  7. Paused to consider.

The next system to implement is the viewscreen. The viewscreen wasn’t a ship’s system in the original Missions, but, to borrow an idea from Lunatic Fringe, why shouldn’t viewscreen damage make it harder to see things around you? Of course, I’ve never done a damage effect like that before, so it might take me a little while to get it right. I’m pondering whether to just skip that for now and move on to the computer and life support systems, which are the only other ones left to do. Doing the computer requires (finally) implementing crew commands, at which point I really should implement the crew themselves, so that’s a bit of a larger subproject. Life support is trivial, though, just a random factor every so often to bring down a crew member if the system’s damaged. All the code necessary for that is already in place.

What exactly was downing crew with the life-support damaged? Gravity malfunctions? Sudden oxygen desaturation? The fire suppression systems going haywire? I wonder about these things!

Maybe at some point I’ll go back to the LRS and made damage steadily decrease the range until they go completely offline.

Maybe after I’m done I’ll go back and add in a bunch of code so that people who want to play Missions 2 can turn on some kind of “Classic Mode” to undo all the tweaks I keep making. Of course, that’ll have to be an easter egg switch…

Stay tuned for further updates!

Missions of the Reliant: Why having two coordinate spaces is a problem.

The best laid schemes o’ mice an’ men / Gang aft agley
– Robert Burns, “To a Mouse, on Turning Her Up in Her Nest, with the Plough”

The torpedos do work, there’s no doubt about that. There’s just one problem: Due to the fact that velocity in my code is expressed in terms of the game’s galaxy coordinate space rather than screen coordinate space as Mike’s code did, my torpedos have different physics than his.

In the original Missions, a torpedo once fired would have the same visual velocity no matter how the player’s direction and velocity changed. For example, a torpedo would take the same length of time to go off screen whether the player continued at full speed or hit full stop immediately after firing.

In my port, a torpedo obeys more traditional physics: If you fire a torpedo from full speed and then hit full stop immediately, it will zoom off the screen at twice the apparent velocity. If you fire from a full stop and immediately accelerate to full speed, you’ll practically run the torpedo over (though they move fast enough that one can not in fact actually do so).

Implementing the old behavior essentially means installing a velocity listener on the player and adjusting the torpedo’s absolute velocity as the player’s delta-V changes. This change, implemented more sweepingly, would bring back an interesting behavior of the old game. Try launching Missions in SheepShaver and holding down forward thrust and left turn immediately; the starbase sprite will move out of position relative to the player ship.

The old behavior is almost certainly not preferable for starbases and planets and enemies. But it certainly made aiming torpedos a bit easier, based on a bit of testing I’ve done versus the working fighters. Even the AI of the fighters has an easier time hitting me with “stable-velocity” torpedos than it does with realistic physics.

I’m at a bit of a loss for which way to go with this. I’ll continue onto implementing other things, as coming back to this issue is always possible.

Missions of the Reliant: Belay that phaser order! Arm photon torpedos!

Torpedos now work.

There are some minor glitches, mainly that it should only take two torpedos to destroy a fighter on easy difficulty, not six, but that’s the only remaining issue with the torpedos themselves. I already know the cause (the damage factor is randomized twice, which produces completely wrong numbers) and I’ll fix it next.

I’d like to apologize for taking so long to get done with what may seem like a simple thing. There were two major issues that made torpedos so difficult:

  1. There was an underlying graphical error across the entire game that had gone more or less unnoticed until now because torpedos were the first sprites to be severely affected by it. It seemed that OpenGL was doing linear filtering on textures when scaling them to the power-of-two rectangles per GL_TEXTURE_RECTANGLE_ARB instead of nearest neighbor. Problem: I was calling glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST), ditto for GL_TEXTURE_MAG_FILTER. Why wasn’t this working? I tried a long list of solutions, including subpixel offset (glTranslated(0.375, 0.375, 0.0)), switching to ARB_non_power_of_two (which failed completely for reasons I still don’t understand), and texture padding. Finally, it dawned on a friend that I was calling glTexParameteri() only once, in -prepareOpenGL, instead of each time I did a glBindTexture(). The assumption was that texture parameters worked the same as the rest of OpenGL, such that state is sticky once set. Fail. Setting the parameters before each glTexImage2D() fixed the problem. That was a fun week of frustration.
  2. I had not, until now, implemented collision detection. If you look carefully at Missions, you find that collision detection is actually only necessary in exactly two places:
    1. Torpedos (including standard player and enemy torpedos, antimatter torpedos, and the planet-busters fired by the battleship).
    2. Missiles (as fired by defense satellites)
    It took some time to implement collision detection, partly because I’d made some bad design decisions in the code much earlier on that had to be fixed to make it work in any reasonable way.

With torpedos working, we’re on the home stretch. Almost everything else is assembling components that already exist in the code. Stay tuned for further updates!

Missions of the Reliant: All hands, abandon ship, I repeat, all hands-

The laser cannon now works, and can destroy fighters.

The sound playback is still just slightly off, but otherwise all is good. The display issues with the laser and target scanner are fixed, the damage coefficients are corrected (the only reason the laser works too well right now is the fighters haven’t had their shields set to the correct type yet).

My current short-to-medium-term list of things to work on:

  1. Fix the sound issue with the laser.
  2. Implement the shield type selection for fighters.
  3. Implement torpedo holds, torpedo launchers, and torpedos.
  4. Implement the various scanner systems (lrs, sector, viewscreen) for the ship (this means they’ll be able to take damage and go offline as intended).
  5. Implement life support. This also involves being able to take damage and go offline, making crew members start dying.
  6. Implement the computer. This represents the final missing system on the player’s ship and will also give me an excuse to implement the keyboard command interface.
  7. Implement the crew members. With the keyboard command interface in place, this is just a matter of tying them into existing code.

After that comes messaging capabilities (“Captain, the laser cannon is offline!”, “Captain, we’ve received a message from Alliance HQ.”), more weapons (missiles, tractor beam, the battleship planet-buster – I plan to call it an Illudium Q-36 Explosive Space Modulator, and a secret easter egg I’m not gonna tell you about), the rest of the enemy types (battleship, cruiser, rebel cruiser, laser satellite), the interface for hailing and interacting with a base (repairs, medical facilities, mat-trans, crew transfer), and the various items that add bonuses to the player’s ship (hyperspace jump drive, super laser couplings, laser and shield types, etc.). Then comes the overall mission logic, and that’s effectively the whole game. It looks like a lot, but about 70-80% of the framework is now in place.

Oh, and when I do the cloaking device, instead of just an expanding wave, it’ll be an alpha-blended 75%-opaque expanding wave over a fading-out ship. OpenGL makes this kinda coolness so very easy.

Stay tuned for more news about my progress.

Missions of the Reliant: Their coil emissions are normal.

More status!

  1. The radar is implemented and functioning.
  2. A whole list of off-by-one pixel errors are fixed.
  3. A subtle retain cycle KVO crash is fixed.
  4. Most of the target scanner bugs are fixed.

I say “most” in that last because I’m not sure if the final bug can be fixed. The cocoa-dev mailing list seems dubious (click the link for a description of the problem). If there isn’t a method, I’ll lose a bit of look-and-feel in the target scanner, hardly showstopping but definitely annoying.

Screenshots of the working radar coming soon!

Missions of the Reliant: They’re locking phasers.

“Lock phasers on target.” – Khan
“Locking phasers on target.” – Joachim
“They’re locking phasers.” – Spock
“Raise shields!” – Kirk
“FIRE!” – Khan

The Reliant now has targetting and scanning systems implemented. There’s still several bugs to work out, but the basic system is in place. When that one little fighter I put in as a test shows up, the ship can lock onto it. Of course there’s no indication on the radar (since there isn’t a radar yet) and no way to destroy it (since there isn’t a laser cannon – though there are laser couplings – or torpedo holds or torpedo launchers yet), but at least we can scan it! Or we could if fighters weren’t always unscannable. Oh well.

Still, that little flashing box on top of the fighter is darn aggressive.

The reason I don’t have more to show than a buggy targeting system is I spent the majority of the time implementing it also working out a huge mess of memory management bugs I’d been ignoring since day one. Leaks, retain cycles, overreleases, you name it. What kills me is that the Leaks tool missed all but a very few of them. I ended up with manual debugging of retain counts by calls to backtrace_symbols_fd(). As uuuuuuuuuuuuuuuuuugly as lions (Whoopi Goldberg, eat your heart out). In the end a few tweaks to the way things were done were in order. Too much work being done in -dealloc when I had a perfectly good -teardown method handy that functions much like the -invalidate suggested by the GC manual.

Why aren’t I using GC and saving myself this kinda trouble? Frankly, given my current understanding of things, I think GC would be even more trouble than this! This, at least, I understand quite thoroughly, and I have considerable experience dealing with the issues that arise. I know how to manage weak references properly to avoid retain cycles and how to do a proper finalize-vs-release model. I haven’t even gotten tripped up by hidden retains in blocks more than once! Yes, I screwed it up badly here, but that’s because I was paying very little attention. I do know how to do it right if I try, and now I’m trying.

Garbage collection, on the other hand, is a largely unknown beast to me, and from what I’ve read on Apple’s mailing lists, the docs Apple provides are very little help to developers new to the tech. The hidden gotchas are nasty devils, much worse than hidden retains in blocks. Interior pointers and missed root objects come to mind, especially since I’m targeting 10.5 where GC support was still new and several bugs in it were known to exist (and may still). Apple chose to provide an automatic stack-and-heap scanning collector, whereas I would only have been comfortable with a manual heap-scanning collector, which is really little more than autorelease anyway. In such a light, the model I’m familiar with and clearly understand seemed a much better choice than trying to learn an entirely new paradigm for this project. Ironically, I still chafe at manual memory management in C++ projects, especially the lack of autorelease, and as with GC, I don’t understand such things as auto_ptr and shared_ptr well enough to get any use of them. Templates make me cringe.

With the targeting scanner implemented, all I need to do is debug it. The next step will be to write the radar, so as to double-check that the fighter AI is working as it should and that the target scanner is de-targeting properly when something falls out of range. After that I need to test the scanner versus multiple targets, especially the new smart-targeting mode I’ve added as an easter egg. What can I say, it always drove me nuts that it targeted “the next enemy in the internal array of enemies” rather than “the nearest enemy to my ship”. But finding how to enable it is left as an exercise to you nostalgic people like me who’ll actually play this port :-).

Come on, iTunes. Jesse Hold On – B*Witched? *punches the shuffle button* 太陽と月 – 合田彩. Much better! Sorry, interlude *sweat*.

Anyway, once the scanner can handle multiple targets, it’s time to implement the third and final component of the laser: the cannon. Time to blow things up with multicolored hypotenuses of triangles! I might even study up on a little QTKit so I can take movies from the OpenGL context to show off. Bandwidth, though; this blog isn’t exactly hosted off DreamHost. (Linode actually, and they’re really awesome). Oh well, we’ll see. Maybe I’ll even leave the feature in as another easter egg…

To summarize, the current plan is:

  1. Fix bugs in target scanner.
  2. Implement radar.
  3. Spawn multiple targets for the target scanner.
  4. Implement laser cannon.
  5. Maybe implement movie capture of gameplay.
  6. ???
  7. Profit!

I’m not making it up as I go, I swear!

Missions of the Reliant: Watch it, you’ve got one on your tail!

Missions of the Reliant version 3.0 now has the framework for enemies, enemy AI, and those infinitely annoying little fighters that everything lauches in droves at you and you can only hit by draining all the charge from your laser couplings. It took some work, let me tell you.

Mike’s original code expresses differences between facing angles as a function of which sprite is being displayed. Efficient. My code expresses differences between facing angles as atan2(-distanceY, distanceX). Mathematically correct and conceptually accurate.

‘Course, then “am I facing the player within a 120-degree arc?” becomes a completely different numerical test. Didn’t help that you kept setting variables you never used anywhere, Mike :-). Originally, I tried to use pretty much identical code for enemy movement as player movement, but it became clear that there were just too many quirks to it.

The fighters especially have an interesting AI about moving:

  1. Calculate distance from me to the player. If too high, return to origin, else continue. (Target determination.)
  2. Calculate angle from me to the player. If I’m not facing that angle exactly (difference between facing and calculated != 0), turn towards it. (Aim.)
  3. If I’m facing the player within 120° of arc, apply thrust N. (Thrust.)
  4. If I’m within distance D1 of the player, reduce speed by 10%. (Falloff.)
  5. If I’m within distance D2 of the player, and I have a loaded torpedo, and I’m facing the player exactly as in step 2, fire my weapon. (Attack.)
  6. Repeat every tick (or every other tick depending on preference setting) of the game timer.

Sounds simple? The fighter has to track its target, its current vector, its ideal vector, the difference between those two, its distance from target, and its firing delay, and constantly adjust all parameters accordingly. The code specifically intended for fighters is 118 lines including comments. Add 134 lines for code that applies to every enemy, 176 lines for code that applies to all game objects, 50 lines for code that applies to anything physics-capable, and 87 more lines for code that applies to everything that needs to do things based on the game timer. Subtract roughly 50 from that for comments and you get 500 lines of code just to drive that simple little AI, not counting the game timer itself or any of the drawing logic.

And I haven’t implemented the weapon, collision detection for the weapon, or the return to origin logic yet. And it’s got a couple of glitches as is, like if the fighter happens to spawn at exactly a 90, 180, 270, or 0-degree angle to the player while said player is at a full stop, it moves in a straight line rather than arcing like it should. Not sure if that bug’s in the original game since it’s next to impossible to set that particular scenario up deliberately without hacking source.

Did I mention that due to several stupid errors on my part, I ended up having to go back to the original fighter model in Infini-D and re-render it, then use Photoshop Elements to recreate the 36-phase sprite from that render? That was a fun two hours. On the other hand, the fighter model looks more “cool” now. It’s also a little harder to see. Sigh.

If anyone’s interested, here’s a couple of screenshots. I’d post a movie but I don’t have any instantly available way of making one and I’m too lazy to pursue the less instant ways.

Missions of the Reliant Fighter 1 Missions of the Reliant Fighter 2