Glad I didn’t wait any longer to do that

I’m a little peeved at myself right now for assuming that XNA development magically lets you develop for Windows Phone, PC, and XBox360 at the same time without any code changes. I can’t take all the blame for believing this — it’s very strongly implied all over the documentation and marketing literature. Still, today I decided I should figure out now just how the game would look and run on the 360, so I bought my license (more on that in a bit) and started what I naively thought would be a relatively easy process. Hours and lots of code changes later, I got it all working:

Microsoft’s directions for this process make it sound incredibly simple, and conceptually, it was. You start by paying $100 for a subscription to the “because fuck you, that’s why” service, which is required to run games on your 360 in development mode. The actual reason, I think, is that Microsoft wants to prevent a secondary games market revolving around connecting your PC to your XBox, so they make that functionality expensive enough the average non-developer wouldn’t pay it. This was the only part of the conversion process that actually proceeded without a hitch. Thanks for taking my money, Microsoft. You get an A+ on that part of it.

I was surprised to see a bunch of errors in my first attempt to build my converted project. But as it turns out, there are quite a few library incompatibilities when moving from PC to 360. For one, it’s constrained to .NET 3.0, when I’ve been used to 4.0 everywhere (not a huge deal). But more frustratingly, big chunks of functionality in the collections library are just … gone. For example, there’s no such thing as an ISet on the 360 Runtime. There’s also no SortedList, and the List class is missing a bunch of useful methods and extensions like Find() and RemoveAll(). I was confused at first, but once I figured out what was going on, it was relatively straightforward to fix these issues. For example, you can emulate a Set pretty easily with a Dictionary, and in fact Farseer already provides such a class. But be warned: it has a bug in the Add method which will throw an exception if you add the same element twice.

For missing extension methods, I whipped up something like so:

using System;
using System.Collections.Generic;
using System.Linq;
using FarseerPhysics.Common;

namespace Arena.Xbox {

    // Just here to make this namespace non-empty on windows
    public static class Dummy {
    }

#if XBOX
    public static class CompatibilityExtensions {
        public static void RemoveAll<T>(this List<T> theList, Func<T, bool> predicate) {
            List<T> entitiesToRemove = theList.Where(predicate).ToList();
            entitiesToRemove.ForEach(e => theList.Remove(e));
        }

        public static void UnionWith<T>(this HashSet<T> set, IEnumerable<T> other) {
            foreach (T o in other) {
                set.Add(o);
            }
        }
    }
#endif
}

Now I can use normal extension methods regardless of runtime and the right thing will happen.

The final issue was a bit dicier: I needed GZipStream support in order to read the TMX files my map editor produces, and there is no System.Io.Compression namespace in the Compact Framework. Luckily, someone else has a build of System.Io.Compression for CF.

That was enough to get me compiling. Walking around and shooting up the level, as I like to do, I noticed pretty terrible performance when there were lots of physical bodies interacting at once, such as happens when I create a shatter animation. It turns out that XBox 360 is just a lot worse at crunching floating point numbers than even a moderate PC is, and there’s really not a lot to be done but tune your game to scale back the demands placed on the physics engine. In my case, that means reducing the number of shards produced from a shatter effect by 75% when targeting the 360:

#if XBOX
                    int numPieces = 4;
#else
                    int numPieces = 16;
#endif

It still looks nice on the 360 with this simplification, although some of the wow factor goes away, obviously. There may be some other knobs on Farseer that I haven’t learned how to twist yet — my initial tweakings didn’t seem to make much of a difference.

So that wraps it up for the initial XBox 360 port. I don’t wish I had done it sooner, but I’m glad I didn’t put it off any longer. I can’t even imagine the deep depression I would enter if I had waited until the game was finished to discover all this work.

NPCs and conversation

One-sided conversation for the time being. I don’t think I want a silent protagonist, but that has worked pretty well for a lot of games…

Dialogue won’t be a huge part of the game, but it will play an important role in plot exposition at key points, as well as being a source of humor and secrets.

As you can see, when you get close enough to the NPC, you get a context-sensitive action pop up above their head. Then any button will advance the dialogue.

For now the NPC is a copy of the main character without his weapon. Farther down the road, I’m going to have a casting call among my friends to do some motion capture to get some diversity in shape and size among the NPCs.

The font is called November, and it’s one of a bunch of free pixely fonts I have my eye on. I’m still thinking about whether I want each NPC to speak with a different font, or just a different color. It’s probably something I’ll have to play around with to see if I like.

Taking damage and a new background

I implemented a quick pixel shader to make characters flash when they take damage. See it in action, along with a slightly less dopey background image, here:

On my first pass, I was trying to toggle parameters on the shader multiple times during every round of the SpriteBatch Begin() / End() lifecycle, as in the following illustration:

_spriteBatch.Begin(0, null, null, null, null, effect);
foreach ( IGameEntity ent in _entities ) {
    effect.Parameters["MyParam"].SetValue(ent.ParamValue);
    ent.Draw(_spriteBatch, _camera);
}
_spriteBatch.End();

That doesn’t work — all drawn entities flash at the same time, because they all end up with the same shader parameters. This makes sense when you actually stop to think about what a SpriteBatch is and how it has to function. Essentially, the graphics card doesn’t do any work, and therefore no shader functions are called, until SpriteBatch.End(). So no matter how many times you tweak Effect parameters in between Begin() and End(), only the last one will take effect, and do so globally.

There are at least two solutions to this problem and possibly a third that I haven’t tried:

  1. Just draw each sprite in its own Begin() / End() pair. This has performance constraints, but for a small number of sprites it’s perfectly doable. This is what I’m doing at the moment.
  2. Group the sprites into batches where the Effect should be the same, then draw each batch in its own Begin() / End() pair. A little more work, and it might be a pain to get the draw order right, but also doable.
  3. Encode information in the Color passed to the shader function via the call to SpriteBatch.Draw(). This should enable you two switch between different modes of operation multiple times in the same draw batch — although I haven’t tried this yet.

This effect will be used pretty extensively in the game, with different colored silhouettes forming an important element of the visual style.

Boom

I hooked up the bomb to the game world’s physics model, doing a bit of other cleanup along the way. Here’s what it looks like:

It can destroy certain blocks as well as harm enemies. Unlike other weapons I’ve implemented, it has an area of effect separate from its physical occupation of space — quite a bit larger in fact. Ideally this would be a circular radius of destruction, but I found that a rectangular area works about as well and allows you to very easily query Box2D about the game world, like so:

AABB aabb = new AABB(_body.Position - new Vector2(0, TileLevel.TileSize / 2 - Height / 2), 
                     ExplodeRadius, ExplodeRadius);
_world.QueryAABB(fixture => {
    if ( fixture.GetUserData().IsDestructibleRegion ) {                    
        var hitTile = TileLevel.CurrentLevel.GetTile(fixture.GetUserData().Destruction.Position);
        TileLevel.CurrentLevel.TileHitBy(hitTile, this);
    } else if ( fixture.GetUserData().IsEnemy ) {
        fixture.GetUserData().Enemy.HitBy(this);
    }
    return true;
}, ref aabb);

In case it isn’t obvious, GetUserData() is an extension method I wrote on top of the Fixture and Body classes, which basically just handles a null check and cast to my custom UserData class. Extension methods are one of my favorite additions to Java in C#. It may seem like a small piece of syntactic sugar, but it makes a big difference in readability.

One thing about C# that I actually like less than Java, and which has been bothering me lately, is that a method must be explicitly declared virtual in order for a subclass to override it. This is the exact opposite route chosen by Java, where a method can be overridden by a subclass unless it is declared final. As far as I can tell, there’s no good reason for this choice, except maybe as a hold-over from C++. If you happen to know why the designers of C# thought this was a superior choice, please let me know in the comments!

Laying bombs

I whipped up a quick and dirty bomb animation that you can lay while using the scooter. Check it out:

One thing I like about this animation is that, despite its general crappiness, there’s a very clear visual indicator of how long until the bomb goes off, something I’m often bothered by the lack of in games of this nature.

The bombs don’t actually affect the game world when they explode yet, but that’s a relatively simple addition for tomorrow.

A good illustration of Hofstadter’s Law

Hofstadter’s Law would make an excellent motto for most software development.

It always takes longer than you think, even when you take Hofstadter’s Law into account.

Getting the bugs ironed out of the scooter has been a pretty good demonstration of this law, with new bugs popping up just as soon as I smack down existing ones. But I did make quite a bit of forward progress, including restricting standing up in tight overhead spaces. I also implemented the ability to manually control the game’s update loop in debug mode. Take a look below:

I probably should have done the latter a long time ago — it allows me to visually inspect things that happen too quickly otherwise, which describes a lot of the trickier Box2d edge cases.

The biggest non-bug hang up was projecting a future shape into the game world to see if it overlapped. I tried a bunch of different techniques, including futzing around with sensors some more, but the one that worked best was good old ray casting. Here’s an example, determining whether the character has enough clearance to duck down into the scooter position:

Vector2 startRay = new Vector2(_body.Position.X,
                                _body.Position.Y + CharacterDuckingHeight / 2 -
                                CharacterScootingHeight / 2 - .02f);
Vector2 endRay = startRay + new Vector2(forwardClearance, 0);
bool roomAhead = true;

_world.RayCast((fixture, point, normal, fraction) => {
    if ( fixture.GetUserData().IsDoor || fixture.GetUserData().IsTerrain ) {
        roomAhead = false;
        positionCorrectionAmount = ScooterForwardClearance - Math.Abs(point.X - _body.Position.X) +
                                    .01f;
        return 0;
    }
    return -1;
},
                startRay, endRay);

My current issue seems to have to do with unavoidable floating point error when manually moving the character around the simulation world. No matter how precise the calculation, in some instances (but not all!) Box2D decides to fire an OnSeparation event when the character’s Body is resized and repositioned, even though the bottom edge of the shape stays in the same place (or as close to same as floating point allows). I’m not sure at this point if I’ll try to revisit destroying and recreating the Body, or hack the event handlers in more subtle ways.

Finally, as promised, a picture of the bacon apple pie I made while on the east side of the state.

Check out that bacon weave

It’s an easy dessert to make (provided you get a pre-made crust), and well worth it. The bacon grease soaks into the crust for an incredibly delicious flavor combination. Yum.

Scoot scoot

I got the scooter (mostly) working today. The scooter is my game’s answer to the morph ball, a way to get into tight passages. It’s kind of a little powered wheel that will pull you along as you crouch way down, helped by some zero-friction knee pads I guess, probably. Luckily, it’s easy to science-fiction your way out of this kind of issue. Also, there’s going to be some handy little bombs you can drop while rolling along. Here’s what it looks like.

After implementing a (mostly) working solution, I understand the wisdom of just rolling your main character up into a one-tile-wide sphere, despite that being physically impossible. The main difficulty with having your main character suddenly lie down or stand back up is that you have to change the shape of their simulated body in the Box2D physics engine. There are two ways to do this, both of which have drawbacks.

  • Destroy the Body and recreate it in the same place but with a different shape. Don’t forget to register all of your collision handlers on this new object, and make sure none of them fire incorrectly on the first simulation time step!
  • Get the shape of the body and tweak it. This will cause you to pass right through solid walls if you’re not careful about it.

Stay out of the walls, you idjit!

This latter problem is caused, as an educated guess, by Box2D incorrectly caching the collision data for a body after its shape has been altered, but I wouldn’t bet money on that analysis. Changing the shape of a body in Box2D is surrounded by all sorts of caveats in the documentation and online, which is why most people recommend destroying and replacing it instead. But as long as you’re not changing the number of vertices in the shape, you should be (mostly) fine.

In my case, I just needed to nudge the character away from the wall before changing the shape. This problem was exacerbated by the fact that I’m doing a translation as well as a shape change, so the Body ended up farther inside the wall than it would have otherwise.

Now I just need to solve the opposite problem — not allowing standing back up when the space overhead is too tight.

Shattering terrain and more futzing with Box2D

I went ahead and applied the shattering animation I wrote yesterday to terrain destruction to see how it looks. Answer: pretty nice!

I also finally fixed a number of outstanding bugs having to do with body destruction in Box2D. One had to do with tiles occasionally recreating themselves in the player’s space, causing him to get nudged around or even fall through the terrain entirely. That one was a simple error from when I changed the tile coordinate system to use the upper-left corner of tiles as their canonical position, rather than their center, which is how Box2D’s bodies work. Simple fix, difficult to track down.

The other was more complex, and involved a total rewrite of how I was answering the classic “am I standing on the ground” question. You might recall that I tried to solve this with sensors earlier in the project, but even after patching Box2D in an attempt to make it more reliably notify me of collision / separation events, I was still seeing incorrect behavior on occasion. Today, I noticed that when shooting out the tile the character was standing on, Box2D was only sending an OnSeparation event about half the time. This meant that even though the character was falling through the air, he could still jump, and this state wouldn’t be reset until he landed. Not cool.

So while I still have collision / separation handlers on my character, I no longer count on Box2D to tell me when the ground beneath my feet vanishes or is recreated. Instead, I follow the naive (but plenty performant) approach and examine all the contacts on the character body.

protected void UpdateStanding() {
    bool isStanding = false;
    bool isTouchingCeiling = false;

    var contactEdge = _body.ContactList;
    while ( contactEdge != null ) {
        if ( contactEdge.Contact.IsTouching() && contactEdge.Other.GetUserData().IsTerrain ) {
            FixedArray2<Vector2> points;
            Vector2 normal;
            contactEdge.Contact.GetWorldManifold(out normal, out points);
            if ( normal.Y < -.8 ) {
                isStanding = true;
            } else if (normal.Y > .8) {
                isTouchingCeiling = true;
            }
        }
        contactEdge = contactEdge.Next;
    }

    IsStanding = isStanding;
    IsTouchingCeiling = isTouchingCeiling;
}

Then I also call this method whenever the terrain changes to make sure that the character knows he’s no longer standing when the ground underneath his feet disappears. I also reverted my patch to Box2D, so I’m not doing duplicate work in these cases. It seems to work perfectly so far.

Missiles and a frivolous death animation

I implemented the basic missile weapon, which does five times as much damage as a normal shot and can destroy tiles that the normal shot cannot:

Then I decided to do something a little more interesting algorithmically and implemented a cool “shatter” animation for when enemies die:

On a more personal note, we recently lost another chicken to a neighborhood raccoon. It couldn’t get into the coop, but reached through the wire, grabbed the bird by the neck, and decapitated it trying to pull it through the chicken wire, leaving its headless corpse inside the coop. Honestly, I never suspected backyard chicken raising would be this gruesome. R.I.P. Carrie.

I picked up two new pullets from the grange to give Charlotte some company, but they’re not getting along very well. I’m sure the much older hen will eventually accept Ygritte and Buffy as her sisters, but she’s being a terrible bully right now.

Back from vacation with health status bar

I was on the east side of the state and out of internet range, mostly doing the best water skiing of my life and eating amazing food — one night we made an apple pie with a woven bacon top (pics forthcoming). But I’m back now, and ready to get back to serious work.

To start, I’ve gotten basic health display and health pickups working:

Eventually the health overlay will be the same color as the main character, which 1) not be bright green, and 2) change when using various equipment in ways I’m not sure of yet. It also seems like it needs to stand out from the background quite a bit more, but I’m torn on how to do that, so I’m leaving it alone for now. I’m trying not to fiddle overmuch with any particular aspect of the game once it’s at least working — there will be plenty of time for polish when things are farther along.

I’ve also got a partial implementation of the first alternate weapon, missiles, that I’m waiting to post until I finish it tomorrow. Then it’s on to a couple experimental movement tools, and possibly some enemy destruction effects.