It’s been another week of various gameplay tasks, bug fixes, and editor work. I don’t have a strong thematic hook to tie all these bits together this week, so…it’s time for another Grab Bag!
I’m getting close to wrapping development on the biped enemy. I still need to modify his behavior when he starts pursuing the player, to increase foot speed and disregard the edges of platforms, but otherwise, I’ve knocked out a lot of the big issues here. When this guy initially spawns and is unaware of the player, he’ll patrol back and forth, as I showed in last week’s video. More recently, I’ve added a line-of-sight test to the player character. Once he has eyes on the player, the biped will begin pursuing, close to melee distance, and attack. I’m pretty happy with how this feels already, but I’ll probably want to continue tuning it to strike the right balance between fairness and difficulty. It doesn’t feel right when the enemy can immediately recover from damage and knockback and return fire, but combat becomes trivially easy if enemies can be caught in a loop of taking damage and being stunned. I don’t yet have a good solution for that one, but I’ll be taking a look at similar games soon to see how this sort of thing is typically handled.
I’ve been tackling a few bugs recently. One I tweeted about earlier this week after finally discovering a reliable repro.
I was immediately obvious what was happening once I discovered this repro, but this bug had been lingering for a week or two in that “seen once, beginning to doubt my own eyes” state. The issue here stems from reusing technology originally built for keeping the player character attached to moving platforms to attach weapons to their owners’ hands. In the event that a viable attachment base (a moving platform, or, in this case, the player character) sweeps upward into an entity that can be attached to others, it parents itself to that thing, no questions asked.
This could also happen when the biped enemy jumped into the player’s sword, and I had seen this happen once or twice during normal gameplay testing as well.
The quick fix was to disallow entities from changing bases if they’re already hard-attached to something else. As I mentioned in a previous video, a “hard attachment” is something which is treated as an extension of the thing it’s attached to, rigidly moving where its parent moves with no regard for collision. By comparison, when the player stands on a moving platform, they are “soft-attached” and will try to move with the platform, but will stop if they collide with a wall.
I had encountered another bug a few times in the last couple of weeks that had me stumped. Infrequently, during normal gameplay, I would get a crash with this message:
I had run across this one a few times while testing from the editor (i.e., running a release build with no debugger attached), but I hadn’t been able to get a repro in a debug build, nor could I find any reliable repro steps.
Eventually, I did hit this while debugging. It was a memory access violation, incurred when attempting to do an initial zero-time tick on an entity that had been created in the previous frame but which had been immediately destroyed by some other force.
That information was sufficient to theorize what was going on, and from there, I was able to narrow down a repro. What was happening (and this explains why the bug was so rare and also why it was difficult to test even once I understood the problem) was that, if the player swung their sword at exactly the same moment they took damage, the game would crash. When the player performs a melee attack, the weapon entity is created in response to playing an animation sequence that wants to spawn an attachment. As such, the sword entity is spawned in the middle of doing normal game loop delta-time entity ticking. Entities spawned mid-tick are held in a list to perform an initial zero-time tick once all other entities have been ticked, in order to ensure they are set up properly. So a pointer to the newly created sword entity is sitting in a list somewhere, and then, as we continue ticking entities this frame, the player takes damage. In response to taking damage, we switch to a hurt/stunned animation sequence, one that does not have an attachment point for a melee weapon. This destroys the sword attachment we just created, but the pointer we had saved off earlier remains. At the end of the tick, we go to do a zero-time tick on it and crash reading bad memory.
In many cases, I can avoid these sorts of issues by using handles instead of pointers, as a handle to a destroyed entity would be correctly recognized as invalid and not dereferenced. In this case, however, I’m dealing with pointers to “tickables,” an abstract class that exists outside of my entity/component hierarchy and is therefore unable to be referenced by a handle. (I should stress this limitation is specific to my engine architecture and could be considered motivation for a more generic refactoring of handles, but I’m not quite there yet.)
One of my development machines is a laptop I purchased in early 2011 for doing some networked game testing. It’s become my primary Linux dev machine by necessity, so I find myself testing my games on it fairly regularly. This laptop has a GeForce G210M video card and is capable of running some 3D games fairly well, so in theory, a 2D game should present no problem. What I’ve found, however, is that more so than any of my other test machines, this laptop gets very pixel-bound very quickly. This has become a problem over time as I’ve continued adding fullscreen passes here and there throughout my game framework to support features like gamma adjustment or blurring out the game scene underneath the menus.
Recently, it occurred to me that if I could bypass some of these default features, I could support an optional high-performance mode. This mode would exclude any CRT simulation rendering, but it would also avoid as many fullscreen draws as possible. It would prioritize speed over visual quality. My goal was to get as close as possible to rendering the game scene directly to the backbuffer. Since I’m already rendering the game scene to a pixel-perfect 256×240 render target texure, I chose not to alter that path, but once the scene has been composed, I render a single fullscreen quad to the backbuffer, and that’s it. Under these conditions, I can maintain a constant 60 frames per second while running in fullscreen on my laptop, so I’m pretty happy with that. I haven’t yet added this option to the menu, so it’s not really a fully supported feature yet, but it can be enabled from the console or config file, and at the very least, I plan to ship that implementation.
I did a little bit of editor work a few days ago in the interest of providing myself with a more comfortable and familiar environment for writing game scripting markup. As I’ve mentioned in a couple recent videos, much of my gameplay — enemy AI, in particular — is authored with XML markup in an editor window. This isn’t necessarily the best environment, and I’ve talked in the past about how large, wordy blocks of markup are usually a good indication that a feature needs to be broken out into a separate visual interface, as I’ve done in the past with animation and collision. However, it seems unlikely that I’ll move entirely away from writing markup by hand anytime soon, certainly not in time to ship the Gunmetal Arcadia titles, so I figured it would be worth my time to make some improvements to the interface as long as I’m going to continue using it for the foreseeable future.
I’ve been using a plain vanilla C# / .NET RichTextBox control for authoring markup within the editor. (For external definitions, I use Notepad++, which handles XML nicely, highlighting paired tags and so on.) RichTextBoxes are a decent place to start, but they don’t do everything exactly as I’d like. In particular, when I’m dealing with blocks of markup, the ability to select multiple lines and tab or shift-tab to indent and unindent is critical. RichTextBoxes don’t do this out of the box; by default, selecting a region and hitting Tab will overwrite the selected text with a single tab. I wound up implementing this myself, checking for lines in the selected region and inserting or removing tabs at the start of each line as appropriate. I also handle the case of hitting Shift+Tab when no text is selected to unindent the current line if able.
The next feature I wanted was Ctrl+F and F3 (and Shift+F3) to search for text in the markup window. As it turns out, C# makes this remarkably simple, thanks to a pair of string searching functions IndexOf() and LastIndexOf(). Between the two of these, it’s easy to look forward and backward from the cursor position to find the previous or next instance of the search phrase. Currently, I don’t support the usual “match case” or “whole word only” criteria, but it’s conceivable I might want these at some point in the future.
Finally, in the interest of legibility (as some of my AI markup has grown to as many as fifteen nested tags in places), I’ve reduced the size of tabs from their default 48 pixels to 25, allowing deeply nested tags to remain more visible.
I’ve been reevaluating my schedule in light of recent Real Life Events encroaching on my work hours. I haven’t committed to any changes yet, but I’m considering shifting videos from Wednesday to Friday. We’ll see. I’ll probably be taking some time off from my regular blogging and video production schedule for paternity leave in early November or thereabouts. What exactly that will look like and how long I’ll be away are still up in the air.