Make Your Time!
It’s going on seven months since my last post, which is kind of pathetic. When finishing a large project, like the WP7 port of Guardian, my brain tends to shut down for awhile for recharging. That, on top of starting a new job back in November, lead to a much longer blogging hiatus than intended. So, how about something simple to get back into the swing of things. And since we’re talking about time…
Very often in video games there is a need to perform some action after a certain amount of time elapses. Examples include deciding when to show the next frame of an animation, deciding when to spawn the next enemy, hiding a message after it’s been displayed for awhile, and so on. For a most basic implementation of this we need two values: something to describe how long we want to wait, and something to track how long we’ve been waiting.
float timerLimit = 2.0f; float timerElapsed = 0.0f;
We also need to pick a unit of time to work with. Seconds seem to be pretty convenient, and that’s what we’ll use here. So the value of 2.0 for timerLimit means we want to wait 2 seconds before doing something.
Once we have these values established it’s a matter of updating timerElapsed each frame and checking it against timerLimit to see if the desired amount of time has passed. Since the game programming API of choice here is XNA, the proper place to do this updating is in the game’s Update() method.
protected override void Update(GameTime gameTime)
{
// grab the number of seconds that have elapsed since the last frame, including fractional seconds,
// so if you're running at 60fps this value will be 0.0166667 more or less, or 1/60th of a second.
float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
// add the elapsed time to our timer
timerElapsed += elapsedTime;
// if the timer has exceed our limit then do something
if (timerElapsed >= timerLimit)
{
// TODO : do something
}
}
Once timerElapsed passes timerLimit then we can perform our action. There’s a problem with this code though. Once the timer exceeds our limit it will keep executing the action every frame thereafter. While this may be what we want sometimes, in many cases, if not most, it isn’t. So we need a way to turn off the timer, or restart it.
To restart it we can simply reset timerElapsed back to zero if we want to the event to fire again in the same amount of time. To stop the timer we can use timerElapsed as a flag and set to -1 to indicate that the timer is inactive. Our timer code now looks like this:
// update the timer if it's enabled
if (timerElapsed != -1)
{
// add the elapsed time to our timer
timerElapsed += elapsedTime;
// if the timer has exceed our limit then do something
if (timerElapsed >= timerLimit)
{
// TODO : do something
// set the elapsed time back to 0 to schedule the event again,
// otherwise set it to -1 to disable the timer
timerElapsed = -1.0f;
}
}
To start the timer initially our code needs to set timerElapsed to 0 which will being the process of tracking elapsed time until timerLimit is reached.
This code practically begs to become a class, so let’s not disappoint it.
public class SimpleTimer
{
public float Limit;
public float Elapsed;
public SimpleTimer(float limit)
{
Limit = limit;
Stop(); // make sure it's not running
}
public void Start()
{
Elapsed = 0.0f;
}
public void Stop()
{
Elapsed = -1.0f;
}
public bool Update(float elapsedTime)
{
bool result = false;
if (Elapsed >= 0.0f)
{
Elapsed += elapsedTime;
result = Elapsed >= Limit;
}
return result;
}
}
Our previous example now looks like this:
SimpleTimer timer = new SimpleTimer(2.0f);
protected override void Update(GameTime gameTime)
{
// grab the number of seconds that have elapsed since the last frame, including fractional seconds,
// so if you're running at 60fps this value will be 0.0166667 more or less, or 1/60th of a second.
float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timer.Update(elapsedTime))
{
// TODO : do something
timer.Stop(); // or use timer.Start() to restart it
}
}
Somewhat less crappy.
Scheduling events like this is one use for a timer. Another thing that’s often needed is the ability to perform an action over time, such as fading out text. The next post will cover that.
Guardian is Certified, Mostly
It appears that Guardian made it through the WP7 certification testing. It’s now ready to signing, which in theory means it’ll be in the marketplace within a few hours. I’ll try to get a final video posted within the next day or so.
After which I can go back to writing more useful posts.
WP7 Analytics
Ben Kane has a great walkthrough for setting up Preemptive’s (currently) free WP7 analytics. If yours isn’t working, this is the place to start.
Incidentally, my problem was forgetting to add ID_CAP_NETWORKING to the manifest.
Guardian Menus
Spruced up the menus quite a bit with some floaty asteroids instead of just the raw text. Looks much nicer I think. The todo list is pretty much empty now. Mostly some final balancing and play testing left to go, and some art work for the various icons and other app store images. If all goes well over the next couple of days it’ll be complete and ready to test when I hopefully get my hardware on Monday.
User Interface for Guardian High Scores and Challenges
Here is my attempt at using XNA to duplicate some of the UI functionality on WP7. Well, not really duplicate so much as “create a passing resemblance to”.
The menu is pretty boring. I’ve been trying to come up with a good idea to make it interesting, and think I finally have something that will be worth the effort. That’ll probably be the next movie.
The first WP7 phones are supposed to be released in the U.S. on November 8th – just one week away. Here’s hoping Guardian works well on the hardware without needing too many optimizations.
My name is Crappy Coding Guy, and I use Texture2D.GetData
In a previous post about texture modification, I mentioned the evils of transferring data from the GPU to the CPU, and then presented an example showing one way to avoid doing it. The post wasn’t really about deformable 2D terrain or collision detection, but was intended to help newer game programmers open up a new way of thinking when it comes to using the GPU to accomplish tasks.
Since that post, and the one showing a video of my WP7 game, I’ve received a couple of questions about how I do the collision detection in Guardian, which would seem to require the use of Texture2D.GetData.
As it turns out, I am evil, and I do use GetData. But, my evilness is optimized based on information from here, here, and here.
- Crater drawing is batched, meaning that rather than draw each one as it’s created, I add them to a list and draw all of them every few frames. This reduces the number of GetData calls – one per batch of craters rather than one per crater.
- After drawing craters to the render target, I wait a few frames before calling GetData to make sure the GPU has processed all of the drawing commands. This minimizes pipeline stalls.
- If I have a pending GetData call to make and more craters come in, the craters will stay batched until the GetData call is complete. In other words, the drawing and getting are synchronized so that a GetData call always happens several frames after drawing a batch of craters, and any new crater draw requests wait until after a pending GetData.
If there are a lot of craters being created the built-in delays can cause some slightly innacurate collision detection since we may be looking at collision data that’s outdated by several frames. At least in this particular game there are never huge numbers of crater adds going on so this isn’t a problem. If there are more than several crater adds they tend to be bunched close together, so the explosion animation hides any visual oddities.
There is one other optimization that I have available but haven’t needed to use. The collision data doesn’t need to be at the same resolution as the drawing data. Basically have two sets of render targets – one for the visual texture, and a lower resolution set for the collision data. Do the GetData on the collision texture and scale everything appropriately when doing the collision check. You have to draw twice – once for the visual data and once for the collision data – but you’re pulling much less data from the GPU which would possibly offset the extra drawing time (this isn’t something I’ve tested yet). You won’t be pixel perfect, but for this type of game that isn’t necessary. As I write this it seems using multiple render targets would eliminate the “draw twice” issue here, but I’ve never done that so some research would be required.
So there you have it. Is this the best or most efficient way? I don’t know – I’m far from an expert on any of this. To be honest, I never actually tested doing this just on the CPU, so it’s entirely possible that that approach is better if there are collision detection requirements. There are also other considerations, such as whether your game is CPU or GPU bound, which would go into determining which method is better suited to your needs. Ultimately, whatever works in your situation is the right method.

