Demoing the pulse width modulator

Early on in the project, I had this crazy idea for a gun modification I thought would be fun to use, and finally finished implementing it today. Basically it’s a cross between a charge shot and rapid fire, with manual adjustments to make it more charge-like or more rapid-fire-like in steps. I’ve been calling it a pulse width modulator with the full understanding that that’s not what those words mean. Anyway, after playing around with it for most of a day I’m convinced it’s fun to use, probably more so than any single element of the game so far. Here I am noodling around with it, as well as demonstrating several new sound effects I created.

Watching this reminds me that I need to globally limit the number of shattered block particles to keep the frame rate up.

The gun has four settings you select by pressing up and down on the D-Pad. Then you hold down the fire button to shoot. As you can see in the video, the lowest setting is a classic charge weapon, and the highest is auto rapid fire. In between the highest and lowest settings, holding the button down results in periodic shots with power roughly proportional to how charged up it is. All the auto-fire modes do roughly the same damage per second, assuming all your shots hit, so this is a power-up that’s more about tactical flexibility and puzzle solving options than brute strength. I do think I’ll seriously increase the power of the first two rapid fire settings – there’s not a ton of reason to use them yet. The setting just below full-auto is interesting as well, because it shoots normal shots not quite as fast as a dedicated player could push the button, but with much less effort. I’m guessing I’ll use that one a lot in my playthroughs.

I also overhauled how the overlay elements (health bar, weapon selection, etc.) are drawn onto the screen. Some of these, especially the mini-map, are actually kind of expensive to draw, so I made some changes to the code to draw all the elements to a texture that I can re-use until something changes. It was getting to be an issue already, and who knows how much more info I’m going to shove up there.

Shockingly inefficient to produce

Shockingly inefficient to produce

For all you XNA devs, I discovered a frustrating issue while I was implementing this change, where the screen would flash purple (the default “transparent” color) for one frame whenever I updated the overlay texture. After a lot of debugging, I figured out that calling GraphicsDevice.Clear() on a screen-sized RenderTarget2D was overwriting the entire screen with purple for that draw frame. This didn’t seem like it should be happening — the clear() operation should work on the RenderTarget, not the back buffer itself — but it was. I fixed it by drawing the texture at the very beginning of the game’s Draw() cycle, then drawing the texture itself when it was time to draw the overlay. This means that for this kind of performance enhancement, you have to split it into two parts, like so:

public override void Draw(SpriteBatch spriteBatch) {
    spriteBatch.Begin();
    spriteBatch.Draw(_screenOverlay, _screenRectangle, Color.White);
    spriteBatch.End();
}

public void PrepareDraw(SpriteBatch spriteBatch) {
    if ( _screenOverlay == null || _needsRedraw ) {
        GraphicsDevice graphics = spriteBatch.GraphicsDevice;
        PresentationParameters pp = graphics.PresentationParameters;
        _screenRectangle = new Rectangle(0, 0, pp.BackBufferWidth, pp.BackBufferHeight);
        _screenOverlay = new RenderTarget2D(graphics, pp.BackBufferWidth, pp.BackBufferHeight);

        graphics.SetRenderTarget(_screenOverlay);
        graphics.Clear(Color.Transparent);
        spriteBatch.Begin();
        _overlayElements.ForEach(element => element.Draw(spriteBatch));
        spriteBatch.End();
        graphics.SetRenderTarget(null);

        _needsRedraw = false;
    }
}

It seems like about half the time I try to do something non-trivial with the XNA graphics framework, I get burned and spend hours debugging. I wonder if another framework would be any easier…

Leave a Reply