2009/10/20 Na-7
2011/01/24 Na-7
 

技術資料一覧に戻る

 

XNAの画面ハードコピー(スクリーンショット)取得サンプルコード

 

注意 この資料は、筆者が自らの経験を記録したものであり、他人に勧めるものではありません。

この資料を参考として行った行為がいかなる結果になろうとも、筆者は責任を負いませんので予めご承知おきください。

 

◎目次

◎概要
◎使用ツール
◎サンプルコード
◎サンプルコードの実行結果
◎サンプルコードの使用方法
◎サンプルコードの解説

 

 

◎概要

XNAでは、実行中の画面をファイルに保存するコマンド(メソッド)は存在しない。

もちろん、PrintScreenキー(ハードコピーキー)を押して画像ソフトで保存したり、専用のツールを使用すれば画面ハードコピー(スクリーンショット)は取得できるが、通常は手作業が発生する。

ゲーム開発においては、これを手作業なしで自動的に行うツールが欲しくなることがある(加工/合成したCG画像を大量に取得したい場合や、キャラを一定角度で回転させた画像を連続的に取得したい場合など)。

本稿では、そういった開発支援ツール等の作成を可能とするために、サンプルコードを掲示する。

 

 

◎使用ツール

ツール名 入手元
XNA3.0(XNA GameStudio 3.0:ゲーム開発用フレームワーク) http://msdn.microsoft.com/ja-jp/xna/default.aspx

 

 

◎サンプルコード

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace ScreenShotSample

{
   
/// <summary>
    ///
This is the main type for your game
   
/// </summary>
   
public class Game1 : Microsoft.Xna.Framework.Game
   
{
       
GraphicsDeviceManager graphics;
   
    SpriteBatch spriteBatch;

       
// キーボード状態の宣言
       
KeyboardState keyboardState;

        // レンダーターゲットの宣言
       
RenderTarget2D renderTarget;

       
// キャプチャテクスチャの宣言
       
Texture2D capturedTexture;

       
// セーブフラグの宣言
       
bool saveFlg = false;

       
public Game1()
        {
            graphics =
new GraphicsDeviceManager(this);
            Content.RootDirectory =
"Content";
        }

       
/// <summary>
        ///
Allows the game to perform any initialization it needs to before starting to run.
       
/// This is where it can query for any required services and load any non-graphic
       
/// related content. Calling base.Initialize will enumerate through any components
       
/// and initialize them as well.
       
/// </summary>
       
protected override void Initialize()
        {
           
// TODO: Add your initialization logic here

           
base.Initialize();
        }

       
/// <summary>
        ///
LoadContent will be called once per game and is the place to load
       
/// all of your content.
       
/// </summary>
       
protected override void LoadContent()
        {
           
// Create a new SpriteBatch, which can be used to draw textures.
   
        spriteBatch = new SpriteBatch(GraphicsDevice);

           
// TODO: use this.Content to load your game content here

            // レンダーターゲットを作成する
   
        renderTarget = new RenderTarget2D(
                graphics.GraphicsDevice,
                400, 200,
                1,
               
SurfaceFormat.Color
            );
        }

   
    /// <summary>
        ///
UnloadContent will be called once per game and is the place to unload
       
/// all content.
       
/// </summary>
       
protected override void UnloadContent()
        {
           
// TODO: Unload any non ContentManager content here
   
    }

       
/// <summary>
        ///
Allows the game to run logic such as updating the world,
       
/// checking for collisions, gathering input, and playing audio.
       
/// </summary>
        ///
<param name="gameTime">Provides a snapshot of timing values.</param>
       
protected override void Update(GameTime gameTime)
        {
           
// Allows the game to exit
           
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
               
this.Exit();

           
// TODO: Add your update logic here

            // キーボード状態の取得
   
        keyboardState = Keyboard.GetState();

           
// ESCキーで終了
           
if (keyboardState.IsKeyDown(Keys.Escape))
                Exit();

           
base.Update(gameTime);
        }

       
/// <summary>
        ///
This is called when the game should draw itself.
       
/// </summary>
        ///
<param name="gameTime">Provides a snapshot of timing values.</param>
       
protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(
Color.CornflowerBlue);
           
// TODO: Add your drawing code here

            // スプライトバッチ開始
            spriteBatch.Begin();

            // レンダーターゲットを変更する
           
graphics.GraphicsDevice.SetRenderTarget(0, renderTarget);

            // グラフィックデバイスをクリア(任意の色に変更可)
           
graphics.GraphicsDevice.Clear(Color.Gray);


           
// (ここで任意の描画を行う)


            // レンダーターゲットをバックバッファーに戻す
   
        graphics.GraphicsDevice.SetRenderTarget(0, null);

           
// レンダーターゲット(画面出力)から画像を取得する
   
        capturedTexture = renderTarget.GetTexture();

           
// 取得した画像を表示する(わざわざやらなくても良い。削除可)
   
        spriteBatch.Draw(
                capturedTexture,
           
    new Rectangle(100, 100, 500, 300),
           
    Color.White
            );

           
// 取得した画像をファイルに保存する
           
if (saveFlg == false)
            {
                capturedTexture.Save(
"TestCapture01", ImageFileFormat.Bmp);
                saveFlg =
true;
            }

           
// スプライトバッチ終了
   
        spriteBatch.End();

           
base.Draw(gameTime);
        }
    }
}

 

 

◎サンプルコードの実行結果

※サンプルコードをそのまま実行した画面

 

※既存のプログラムにサンプルコードを組み込んだ画面

 

 

 

◎サンプルコードの使用方法

// (ここで任意の描画を行う)

上記コメントの位置に任意の描画コードを追加すること。

または、既存のプログラムにサンプルコードを組み込むこと。

 

尚、画像ファイルは「\bin\x86\Debug」に出力される。BMP以外にもJPGやGIFなど様々な形式で出力可能。

 

 

◎サンプルコードの解説

このプログラムでは、レンダリングターゲットをバックバッファーからテクスチャに変更し、テクスチャをファイルに保存している。

レンダリングターゲットについては、こちらの記事XNAヘルプ、またはブログを参照のこと。

 

2011/1/24追記

スプライトバッチの2Dテクスチャ等を表示する場合は、スプライトバッチをネストさせること。
→SpriteBatch.End()が呼び出されないとスプライトの描画が始まらないので、レンダーターゲットをバックバッファーに戻す前にSpriteBatch.End()を呼び出す必要がある

 

inserted by FC2 system