I am honored to announce that I’ve done a guest spot regarding assembly language on the blog of well-known Mac developer Michael Ash. You can find my post at his blog. I highly recommend every one of his posts for OS X and iOS developers of all kinds. Thanks for the opportunity, Mike!
I have discovered that the minimalist markup language known as Markdown is absolutely awesome. Why? Because it’s utterly simple, utterly expressive, easier to type than HTML, and works spectacularly in TextMate.
That is all.
For those of you who are still hoping for Missions of the Reliant news, I want you all to know I have not forgotten or abandoned the project. I will come back to it, hopefully someday soon. I thank all of you who remain from the bottom of my heart for your incredible patience, and hope you’ll bear with me just a little longer!
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!
- 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).
- 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…
- … 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.
- 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.
- 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.
- 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.
- 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!
Unfortunately, I’m a bit of a newbie when it comes to mailing lists, and I had to settle for a Google Group for simplicity’s sake: http://groups.google.com/group/missions-of-the-reliant. It’s members-only, but anyone can subscribe. Please feel free to sign up and comment; it’s open for discussion as well as news :-).
While writing some code to implement a block-based callback on top of some classes which are still stuck in the target-action paradigm, I stumbled across this rather nice little trick for doing so in a category without having to do any memory management tricks at all in retain-release mode. This example comes from adding a block callback to iOS’s
UIBarButtonItem (DR is for Dark Rainfall, of course):
Poof. Proper management of a block’s memory in a retain-release environment without any effort! This little trick could be further simplified by another method on NSObject, something like
- (id)associateBlock:(void (^)(id))b withKey:(const char *)key;, but that’s overkill in my opinion. For completeness’ sake, I also wrapped the whole thing in
#if NS_BLOCKS_AVAILABLE, though on iOS that’s probably unnecessary, as I have no intention of ever developing for <4.0 again, and even on OS X I would use PLBlocks if I had to target Leopard.
For those waiting for Missions of the Reliant news, I beg your patience. I have not forgotten!
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!
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.
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!
As a programmer, I have the dubious pleasure of enjoying overcomplicated, highly technical games such as EVE Online. For those who don’t know, EVE is an MMORPG that functions essentially on the opposite premise from World of Warcraft. Pretty much nothing is done for you in EVE. There’s a million ways to screw up and nothing you can do once that’s happened. It’s rather like real life in that way. Despite its poorly-done Python UI and downright pathetic Mac port (it’s the cider wrapper layer on top of wine emulation), I enjoy the game, primarily because it exposes so much of the “nitty-gritty” details of how its universe works. A player has control over very detailed numbers and data relating to the functioning of their spaceships and even their bodies. Often it’s too much data; it’s very easy to forget one tiny thing and lose millions of ISK (in-game money) and a great deal of time because of it. Neglecting to bookmark a wormhole exit comes to mind. EVE also does nothing for you. To install implants or activate jump clones, you have to manually pause your skill training queue, for example, even though this is something the game could very easily do for you, and there’s no apparent reason to make the player click the extra four buttons.
In any case, the thought behind this whole bit is, games are addictive. This is not a new discovery, for the world or for me, and I don’t expect anyone to be astonished by the revelation. For people such as me, who fall in love very easily with inane technical details and exacting numbers and gated progression (the need to finish task X before being able to learn the details of the task Y that follows), EVE is particularly so. It’s easy to say “I’ll just do one mission and then get to work,” and in a game like World of Warcraft where quests or even group dungeons are typically short these days (vanilla WoW notwithstanding), that would mean an hour of playing a game and then several hours of productive time. Setting aside the question of the “well just one more” syndrome, which is another problem altogether, the same comment made about EVE usually involves suddenly realizing I’ve spent six hours I meant to use for coding just finishing the one task! It always takes longer to blow up NPC ships than the mission description suggests (even using the Cliff Notes available online). Then there’s travel time between areas of a complex to consider, especially in a slow ship like most of the more powerful ones, and time spent salvaging wrecks (an extremely profitable activity well worth the effort if you have the time to spend, especially on more difficult missions), and then there’s organizing and selling/using whatever you gained from the mission and the salvage.
EVE unfortunately has the problem that for some play styles (including mine), play consists of paying intent attention to the same thing happening over and over for an hour or three, most of that time spent with no user input (and what input there is is also repetitive). Taking one’s attention off for a moment lends itself to finding the entire effort wasted. This would be a spectacular thing for some forms of autistic, but I’m not one of them! Oh well. I still like the game, because there’s a very real sense of accomplishment to completing various tasks.
The upshot of it all is that the existence of such games tends to sap the time I’d otherwise spend making progress. Yet, if asked if I’d rather the game be taken away, I have to say no, because I still need the distraction. What I want, really, is more control over the length of the distraction. “Just do it” doesn’t work for everyone, people!
I would recommend EVE Online to compulsives and the technically minded. I would not recommend it for those who don’t have the patience to wait before being able to explore facets of the game. Some of the higher-end stuff takes literally months to gain the skills for.
This post didn’t really have a conclusion, or a solid point. I just kinda felt like getting all that out. :-)
And now one of the rare not-Missions-related posts.
I found myself with the need to run Lua code under iOS. Yes, this is legal according to the current Apple Developer Agreement. Who knew the journey I’d undertake in the process.
Originally, I got it running by just building the Lua source files into a static library and linking it in, then using the C API as usual. Worked like a ruddy charm. But then I decided to get clever. “Wouldn’t it be great,” I thought, “if I could run the bytecode compiler on the source and make them into unreadable bytecode objects?” So originally, I tried piping the source files through
luac and running them otherwise as usual. The story of how I got Xcode to automate this process without a damned Run Script build phase is another one entirely.
Bad header in precompiled chunk.
Docs say, “The binary files created by luac are portable only among architectures with the same word size and byte order.” Fine. x86_64 and armv are both little-endian, but
sizeof(long) on x86_64 is twice what it is on armv7. Duh! Running Stuff on Apple Systems 101. Universal binary, here I come! I built lua 32-bit and lipo’d myself a nice universal binary of luac, ran it via
/usr/bin/arch -arch i386.
Bad header in precompiled chunk.
What? Byte order and word size are correct. So I delved into the Lua source code.
lundump.c, lines 214-226. Precompiled chunks are checked for version, format, endianness, size of
int, size of
size_t, size of Lua opcodes, size of the
lua_Number type, and integralness of
lua_Number. All of which should have been correct- until I remembered that I’d changed the
luaconf.h of the iOS binary’s Lua to make
float. It’s a
double by default.
Rebuild my universal binary of
luac using the same
luaconf.h the iOS project uses. Run it through yet again. Lo and behold, it worked that time. It doesn’t really feel right to me running i386-compiled bytecode on armv7, but since Lua doesn’t even remotely have support for cross-compilation and I don’t feel like jumping through the hoops of making a luac utility on the device without jailbreaking, it’s the best I can do.
I would be remiss if I didn’t remark also upon the journey of learning how to make Xcode automate this process for me. There was more than just running
luac to be done. I wanted my Lua scripts run through the C preprocessor, to get the benefits of
#define. Easier said than done. The C preprocessor doesn’t recognize Lua comments, and while because comment stripping is part of preprocessing I could have used C comments instead, it would have meant changing a goodly bit of code, and messed with the syntax coloring. And more importantly, my sense of code aesthetics. It’s always bothered me that the C preprocessor can be both Turing-complete and damn near impossible to work with (an aptly-named Turing tarpit). So I wrote a pre-preprocessor (also in Lua, naturally) to strip the Lua comments out first. But then I had to parse and handle
#include manually. Oh well. The real benefit of C preprocessing is the macros anyway. It was quite an interesting bit of work making Lua talk to clang; the built-in library for doing things is a little bit lacking. Anyway, the upshot was there were three steps to processing Lua files in the iOS project: preprocess, luac, copy to Resources.
I finally caved in to my sense of danger and went looking for the extremely scanty reverse-engineered documentation on Xcode plugins. It was pretty awful. The API looks to be quite a mess of inconsistently named attributes with strange side-effects. It took me two hours to hunt down the cause of a “empty string” exception as being the use of
$(OutputPath) inside a cosmetic attribute (Rule name). It was hardly perfect even when I declared it done, and then I realized I had the architecture problem again. I had to run a different
luac for x86_64 than for everything else. If i386 was the only other architecture, I could’ve just let it be done by a universal binary, but no, it had to cover armv too. Ultimately it turned out a second plugin was necessary, lest Xcode be sent into a downward spiral of infinite recursion at launch. Ugh. Don’t talk to me about all the horrifying effects the tiniest typo could have on Xcode. I love the one in particular where the application was fully functional, except for builds and the Quit command. Uncaught Objective-C exceptions equals inconsistent program state, people. And it’s not just that the API is entirely undocumented. You get those sorts of weird behaviors even if you never install a single plugin or specification file; the Apple developers don’t always get it right either. The application is a horrid mess, and I find myself desperately hoping that Xcode 4 is a full rewrite. I can’t discuss anything about Xcode 4 due to NDA, of course.
As a side note to all this, compiling extension modules for Lua also turned out to be an unmitigated nusiance. It turns out, you see, that the extension authors out there tend not to run their code on Darwin-based systems, and so all the ludicrous quirks of dyld tend to hit a user of their code smack in the face. Finding out that I needed to pass
-bundle -undefined dynamic_lookup to the linker instead of
-shared was easy enough from the Lua mailing list posts on the subject. Figuring out why that didn’t work either meant realizing I’d built Lua itself with
-fvisibility=hidden for no good reason at all, causing the
dlopen() calls to crash and burn. Figuring out why my self-written pcre interface module randomly crashed with a bad
free() during Lua garbage collection meant debugging and valgrinding like nuts until I found out you’re not supposed to link
liblua.a to the extension module. Static library + linked to both loader and module = two copies of the code. Anyone’s guess which you get at any given time. One could only wish dyld was able to make itself aware of this ugly situation.
If anyone’s interested, give a holler in the comments and I’ll post the pcre extension as an opensource project. It’s not fully featured (in particular it’s missing partial and DFA matching, as well as access to a few of the more esoteric options of the API), but it does work quite nicely otherwise. It’s built versus PCRE 8.10 and Lua 5.1, and is upwardly compatible with the still-in-progress Lua 5.2 as it currently stands.
I promise I’ll get some work on Missions done this week!
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!
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 ;-)
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!
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.
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:
- Designers of any sort, linguistic or otherwise, do not have the power to see into the future.
- 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.
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!
Today’s list of completed tasks:
- Made the torpedos work the old way. You’d think that was simple, but nope…
- Implemented long range scanners as a ship’s system (can take damage and go offline, can be repaired, code isn’t special-cased anymore)
- Implemented sector scanners similarly
- Fixed a long-standing issue with the way explosions were being handled so that they finally look exactly correct.
- Fixed a nasty memory leak with torpedos that was spewing errors to the console.
- 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).
- 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!
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.
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:
- 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_ARBinstead 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.
- 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:
- Torpedos (including standard player and enemy torpedos, antimatter torpedos, and the planet-busters fired by the battleship).
- Missiles (as fired by defense satellites)
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!
With apologies to Pete Seeger and Malvina Reynolds…
Little Tic-Tacs in the boxes
Little Tic-Tacs made of sugar gum
Little Tic-Tacs, little Tic-Tacs, little Tic-Tacs all the same
There’s a white one, and a white one, and a white one, and a white one
And they’re all made out of Ticky-Tacky
And they all look just the same
This came to me when someone said “Tic-Tacs” and “ticky-tacky” to me. That is all.