Posts Tagged xna

Event-driven audio

One of the older items on my to-do list was to give my sound designer a way to change the game’s audio without having to recompile the game in Visual Studio and start it up. Based on some of the improvements I made recently, I was finally able to knock that item off my to-do list.

Below, you can see a short annotated video walkthrough where I demonstrate the technique and show how it integrates with XACT.


There are a few key pieces necessary for this to work.

Read the rest of this entry »

Tags: , , , , , ,

Simple Dynamic Music with XACT

Good music adds a lot to a game, but only if it fits the action occurring on screen. Badly chosen music that doesn’t match the feel of your game, or is inappropriate for the tone of the gameplay, won’t do you much good. Dynamic music is one way to help make sure your music is always a good fit for the action occurring on-screen – it lets you adapt the music the player is hearing based on what’s happening.

There are various approaches for building dynamic music – some games go so far as to create hundreds of short music ‘snippets’ and string them together to create longer, more dynamic songs that never sound the same to the player once. Unfortunately, this is pretty complicated to do, especially if you’re just working with XNA and XACT. Luckily, there are some simpler techniques you can use to build dynamic music.

Below, you can see a short video clip showing one of my experiments with dynamic music. I’ll explain how it works in this post, so you can apply the technique to your games. In this video clip, I have two music tracks playing, and control the volume of one of them depending on whether or not the player character is within the blue rectangle. You can hear the track fading in and out as he moves.

(The track used in this example is ‘Corn Fields‘ by Skyline.)

The approach I’m using works like this: You take a song that you intend to use in your game, and in an audio tool, split it out into multiple wave files, one for each ‘track’ that you want to have control over. Depending on the complexity of your song, you might just want to split it out into a pair of tracks, and fade one of them in when you want the music to get more intense. If your music is more sophisticated and your gameplay has lots of variation, you may want lots of tracks that you can control individually based on what’s happening – fade in some anxious-sounding strings when powerful monsters are on screen, and temporarily fade in some ominous-sounding bass notes when the player is injured, for example.

Read the rest of this entry »

Tags: , , , ,

Threaded Renderer

Lots of changes since last week, but the majority of my efforts were focused on overhauling my approach to rendering.

My basic approach is primarily inspired by Christer Ericson’s post about the approach he uses for ordering draw calls. Some other useful sources of information were Tom Forsyth’s post about the cost of renderstate changes and Guerilla’s presentation on Killzone 2′s renderer from DEVELOP 2007. The Killzone 2 presentation is especially worthwhile since it describes the way they take advantage of concurrency techniques in their renderer.

Until now, the rendering code in my game has been almost entirely immediate-mode; various objects in the game world like tiles and entities had Draw methods that would utilize the game’s GraphicsDevice and SpriteBatch to render themselves, changing render states as needed and generating dynamic geometry where necessary (like for water).

Read the rest of this entry »

Tags: , , , , ,

Camera Constraints

As the level I’m currently building has gotten larger, it’s become obvious that I need a way to control the behavior of the camera – simply centering it on the player isn’t sufficient. While I already had some usable support for panning the camera to show points of interest, and locking it in place while the player performs an action like climbing onto a surface, I didn’t have anything in place for more advanced control of the camera, like constraining it to a region of the level.

So, the first approach I took was simple: I placed a rectangle around the entire level to constrain the camera. For smaller, rectangular levels, this worked good enough – all I had to do was place the rectangle so that you could see all the important parts of the level, and make sure I filled the entire space with tiles so the player didn’t see any ugly empty space while the camera panned around.

But to be honest, that kind of sucks. It means I have to waste time filling in the entire rectangle with tiles, and the camera doesn’t do anything to help give the player a sense of the layout of the environment. Ideally, the camera should be able to automatically position itself so that you can see the important parts of the area around you, and not show you unimportant sections of the level that you might have already passed through, or might be encountering later. Furthermore, it should avoid showing you empty/boring space whenever possible – no point in showing boring repeated tiles to the player when we could be showing interesting parts of the level instead.

The first approach I tried was a relatively simple one: I placed points of interest throughout the level, and then drew lines to connect them using the editor. After that, I assigned a radius to each point, controlling how far the camera would be allowed to ‘drift’ away from the point. The end result was that I had a series of ‘rails’ the camera could follow through the level, of varying thickness depending on the radius of each point.

Read the rest of this entry »

Tags: , , , ,

GPU accelerated particles

During this last week, some of the work I did was to optimize my particle system, since it was showing up consistently on my profiles and I was adding more and more particles to my environments.

There are a few basic approaches you can take when trying to optimize code like my particle system.

  • The fact that you have a large number of particles all behaving in the same way means that you can easily distribute the work of updating/rendering particles across multiple cores, as long as your data structures and libraries are set up correctly to handle it – so one option is to multithread your particle system.
  • The parallel-friendly nature of a particle system also means that it’s possible to offload much of the work involved in rendering particles directly to the GPU, and do it in a shader instead of on the CPU. This is almost always faster.
  • In fact, in many cases, you can even update your particles on the GPU, by storing their state in a texture or vertex buffer and having a shader run over all the particles and write their new state to another texture/buffer. You can then take the new state and feed it into another shader as input to render your particles.
  • And of course, you can always take the standard approach of brute-force optimization, by making your particle system as efficient as possible with the same basic algorithm.

Read the rest of this entry »

Tags: , , , ,

Using PerfHUD with XNA games

If you want to use PerfHUD with an XNA game, you’ll need to make some changes to your source code. Since the PerfHUD documentation only explains how to do this when using the native DirectX interfaces from C++, it can be a bit confusing to figure out how to make it work with XNA, especially since the XNA Framework goes to some effort to prevent your games from starting on graphics devices that might not support its feature set (for example, reference rasterizers). Since PerfHUD presents itself as a reference rasterizer, you have to jump through some hoops.

The solution is to write a custom GraphicsDeviceManager that replaces the default XNA one. Luckily, you don’t have to write very much code to make this work – you just have to do things in a particular way so the framework remains happy. The source code can be found here. All you need to do is add this class to your project (or use the library it comes in), and modify your game’s initialization code to look something like this:

#if !XBOX
            Graphics = new PerfHUDDeviceManager(this);
#else
            Graphics = new GraphicsDeviceManager(this);
#endif

After this, you should be able to start your game under PerfHUD on Windows.

Please note that since the PerfHUD device presents itself as a reference rasterizer, I believe this disables use of some types of hardware acceleration within the framework, so your framerate may suffer as a result when running under PerfHUD, and you might get slightly misleading results when profiling. I consider this to be the unfortunate intersection of two bad design decisions, but not really a bug. If you felt so inclined you could probably work around this issue by hacking up the XNA Framework classes a bit so that they believe the PerfHUD device is a real hardware device.

Tags: , , ,

Threaded EndDraw in XNA (Crouching WaitOne, Hidden Lock)

After finishing up the materials for my Level Up 2009 entry, today I spent a little while trying out an idea I had recently:

One of the problems with using vertical sync in a video game is that it eats into the available CPU time for performing game updates. The way vsync is implemented in most graphics APIs, it causes your Present/EndDraw/SwapBuffers call to block until the card enters vertical blank and the frame is shown to the user. While this is ideal from a correctness perspective, it’s a tremendous waste since it means you can end up sitting there for up to 16 milliseconds, waiting for vertical blank. If your game spends lots of time doing both updating and drawing, all that time could be spent performing updates instead. Ouch.

Currently, my game spends about as much time drawing as it does updating. A significant portion of the time spent drawing (20-30%) is within the EndDraw function. Turning off vertical sync drops the amount of time spent in EndDraw considerably, but introduces tearing. So, as a potential solution, why not call EndDraw on a background thread? While the thread waits for vertical blank, I can begin performing the next frame’s Update, and in the event that I finish updating before the previous frame is visible, I simply wait for that previous EndDraw call before beginning to paint the next frame. In the optimal case, this means I can come much closer to the best possible framerate without introducing tearing, and in the worst case, the cost of rendering an individual frame is only *slightly* increased by the use of thread synchronization. The fact that I’m only doing EndDraw on another thread means that I don’t have to worry about protecting my game data with locks and other synchronization techniques, since the GraphicsDevice doesn’t use any of my game data when performing the EndDraw operation.

So, to test this out, I overrode my Game class’s BeginDraw and EndDraw methods. This turns out to be all we have to do to change the way drawing is performed, because the XNA Framework developers were kind enough to make both of these methods virtual.

        protected override bool BeginDraw () {
            _DrawCompleteEvent.WaitOne();
            _DrawCompleteEvent.Reset();
            return base.BeginDraw();
        }

        protected override void EndDraw () {
            _DrawRequiredEvent.Set();
        }

Of course, at this point, the two events used here are never set, so this code won’t work. Thus, we add a background thread to perform our painting:

        AutoResetEvent _DrawRequiredEvent = new AutoResetEvent(false);
        ManualResetEvent _DrawCompleteEvent = new ManualResetEvent(true);

        public Game () {
            ...

            _DrawThread = new Thread(DrawThreadFunc);
            _DrawThread.IsBackground = true;
            _DrawThread.Start();
        }

        protected void DrawThreadFunc () {
            while (true) {
                _DrawRequiredEvent.WaitOne();
                base.EndDraw();
                _DrawCompleteEvent.Set();
            }
        }

Fairly simple thread programming here: We create a thread, and set IsBackground to true so that it will stop as soon as the main thread exits. The thread spends all of its time waiting for a ‘required draw’ signal, and then performs an EndDraw call. Once the call is complete, it sets another signal to inform the Game class that the previous draw has finished and it’s safe to perform a BeginDraw call (this lets us make sure that we never use the GraphicsDevice on the main thread while the background thread is performing an EndDraw).

Once this is all done, I start up my game, and… the framerate isn’t any different. Huh? What’s more, my frame profiler indicates that Update is now taking ten times as long as it used to, while Draw isn’t any faster. Huh???

In situations like this, it’s always good to consult a profiler to see if you’re missing something important:

profile_01

So, we can see that the DrawThread is definitely doing its job – it calls EndDraw, then waits for a signal asking it to draw again. Both are taking about as much time as we’d expect. But why is Update taking so long…?

profile_02

… oh. Oops.

So it turns out that I was using GraphicsDevice.Viewport.Width and GraphicsDevice.Viewport.Height in my camera code. Accessing the Viewport property caused the XNA framework to call into Direct3D to retrieve the viewport, which acquired the exact same lock being used by EndDraw, causing my main thread to stall until the draw completed. WHOOPS.

This is especially embarassing since the viewport size never changes anyway, so I could have just stored the width/height into constants. After doing just that and starting the game again, the profile looks more like you’d expect:

profile_03

What’s more, this is actually an improvement: With vertical sync enabled, this results in a significant reduction in the amount of time spent inside the BeginDraw/Draw/EndDraw functions on the main thread, which means there’s more time left to perform Updates. This means that I can maintain a solid, smooth 60fps easier on dual-core/hyperthreaded machines.

Even with vertical sync disabled, this is still an improvement, though not as significant – apparently other things are happening inside EndDraw (not a big surprise), so by shifting that work off onto a second thread, I’m still gaining some time to spend performing the next update. When I disable the built in framerate balancer, this brings my framerate from ~350fps up to ~380fps. Not bad for a couple dozen lines of code!

Of course, it’s worth pointing out that the XNA Framework documentation doesn’t make any promises here, so it’s possible that this technique is unsafe. When it comes to concurrency, it’s very easy to do the wrong thing and get away with it – as you might have noticed here, I was doing something utterly stupid and unsafe in my Update function, and I got away with it because the DirectX developers had the foresight to put a lock in the right place. If they hadn’t, my game might have corrupted state from accessing the GraphicsDevice on two threads, and crashed intermittently.

Regardless, this is a handy technique – once I’ve had the chance to do lots of testing on various PC configurations (and the XBox 360), I’ll probably be using it in my game when I ship.

Tags: , , , , , ,

Water

Among the various things I worked on this week, I spent a good portion of time implementing a basic fluid system in the game engine. The fluid system lets me create volumes of moving fluid that alter the player’s physics and can flow down off ledges and interact with objects, so that levels like the aqueducts look and feel more convincing.

The two major pieces of the fluid system are physics and rendering. The physics system is arguably more important, but ended up mostly being a matter of fine-tuning. Here’s how it works:
Previously, every frame I did a sweep of the area below onscreen entities to locate the nearest surface to stand on, and used that to perform some motion and collision detection calculations so that the player can properly move up/down slopes, stand on moving objects, and drop when standing over a gap.

To implement the water system, I extended the standing sweep code to also locate the nearest volume of fluid that intersects the entity, and store it. What this allows me to do is detect whether or not the player character is currently inside a fluid, regardless of whether or not he’s standing on a surface at the time (so it even works while jumping/falling).

Once I had this functioning, I added the ability to attach ‘Material’ information to any piece of geometry in the game, including fluids. These two pieces of functionality combined allow me to control the physical attributes of a surface, and then further alter those attributes when the player is standing inside water or other fluids. This not only allows me to implement slippery surfaces like ice, but cause the player to move more slowly and have different control characteristics when in the water.
In the future, this should also allow me to alter the characteristics of surfaces in response to gameplay events – enemies that spray sticky goo on the ground, spider webs that slow you down, or a potion that freezes water, turning it into slippery ice you can stand on.

After a bit of fine-tuning, I came up with some physics parameters for the basic material types that I’m happy with, that make the differences between various materials obvious without breaking gameplay mechanics. The jumping mechanics were a particularly tough detail – even minor changes to the acceleration and speed characteristics of the player render some of my jumping puzzle prototypes completely impossible to solve, so I had to carefully test against those puzzle prototypes each time I adjusted the physics values for a given material. In the final game, I’m going to have to address this by only using a specific set of materials in each level, so that it’s not necessary to retest the entire game after physics changes.

Of course, water isn’t particularly interesting if you can’t see it, so the other thing I did was build a fairly simple bit of rendering that allows fluids to flow across surfaces and down off ledges.

Read the rest of this entry »

Tags: , , , ,

Content Pipeline integration and deployment

During this past week, one of the problems I tackled was finding a way to deploy builds of my game. When dealing with deployment, an important principle is that the process should be as close to a single click as possible – a complex deployment process discourages you from getting customer feedback, and increases the likelihood that you’ll make a mistake and end up with a failed deployment, which wastes valuable time.

For most of my previous projects, I’ve tended to take either a hands-on approach to deployment, or a completely hands-off one, either building an installer by hand using tools like NSIS, or deploying the project as a ZIP file full of binaries and expecting the end user to install the necessary dependencies and figure out how to get the program running. Neither extreme is ideal, really (though hands-off deployment can be amazing if you manage to set things up such that all the end user has to do is run your game – no install necessary).

Read the rest of this entry »

Tags: , , , ,

Tiled map loader for XNA

Update: Stephen Belanger of Nerd Culture has made some great improvements to the following code, so I encourage you to check out the post about it on his blog.

Early in the development of my game, I used the free and open-source Tiled Map Editor to create levels. It was a big time-saver since it let me worry about more important things instead of investing effort into being able to place tiles down on a map. Later on I decided that the traditional approach to map construction wasn’t right for my project – but I was still glad I’d used Tiled.

Recently I realized that there aren’t very many easy ways for newbie XNA developers to get maps into their games, so I decided it was worth packaging up my Tiled map loader and sharing it with the world. So, I’ve created a simple example that shows how to load Tiled maps in your XNA game on Windows PCs and the XBox 360, and included the loader with it. It’s open-source and free for your use, no strings attached. I hope you find it helpful.

screenshot

Download source code and binaries

Note that it doesn’t have support for isometric tiles or embedded tilesets, because I had no use for either feature. Tiled’s file format is relatively simple, so if you need those features, it should be simple to add them.

And of course, this wouldn’t be possible without the generous contributions of the developers of Tiled, Adam Turk and Bjørn Lindeijer. If you’d like to try it out, you can download it from their website (note: requires Java).

Tags: , , , , , , , , ,