Quick and Dirty Screenshots in PC Games
I do a lot of my testing work on PC. I also like to take screenshots along the way to show off and just watch a project progress. One thing that isn’t so nice is taking screenshots. Sure there’s the good old printscreen, but that’s a bit annoying to me. I have to open up Paint or Paint.net and paste in the image. Then I have to crop the image so it only shows the window contents (I know Alt-Printscreen does just the current window, but I don’t like showing screenshots with the window in them). So to this end I wrote up a nice little screenshot system for my latest project.
Because this functionality is only being used in Windows, we’re going to put it all inside of #if WINDOWS directives so our 360 build doesn’t have any of this code. To start we need to add a few new variables into our game class.
#if WINDOWS private ResolveTexture2D resolveTexture; private bool takeScreenshot; private readonly string desktopDir; private int screenshotNumber = 1; private Thread screenshotThread; #endif
Next we initialize the resolve texture and desktop directory in our LoadContent method:
#if WINDOWS resolveTexture = new ResolveTexture2D( GraphicsDevice, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight, 0, SurfaceFormat.Rgb32); desktopDir = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); #endif
Next we override EndDraw to take care of our screenshot functionality. You’ll note I kick off a new thread to handle saving the data which avoids making my game stutter when I take a screenshot. This is the ‘dirty’ part I was talking about. I didn’t really do much to ensure thread safety here, but in practice I haven’t crashed my game yet and I’ve mashed on my screenshot button for a bit. But as usual, your mileage may vary.
#if WINDOWS
protected override void EndDraw()
{
if (takeScreenshot && (screenshotThread == null || screenshotThread.Join(0)))
{
GraphicsDevice.ResolveBackBuffer(resolveTexture);
takeScreenshot = false;
screenshotThread = new Thread(() =>
{
string filename;
do
{
filename = string.Format(
"{0}{1:00}.png",
Window.Title,
screenshotNumber++);
} while (File.Exists(Path.Combine(desktopDir, filename)));
resolveTexture.Save(
Path.Combine(desktopDir, filename),
ImageFileFormat.Png);
});
screenshotThread.Start();
}
base.EndDraw();
}
#endif
And that’s basically it. Now just set your takeScreenshot to true when you need a screenshot and everything will handle itself. What I did was add a bit of input code and trigger screenshots with F12, but you can feel free to trigger them elsewhere. Another great benefit of this over printscreen is that you can trigger screenshots pro grammatically meaning that you can have certain events or timers or whatever triggering screenshots, making it easier for you to get some interesting screenshots of your game running.
Possibly Related Posts
(Automatically Generated)Quick attempt at more complex animations
Dynamically Refreshed Assets in XNA
A More Robust Exception System
Building XNA 2.0 Games (A Review)
Indexing Xbox LIVE Community Games
