Visual Studio 2008 Express Editions - XNA Game Studio 入門...

24
Silverlight をインストールするには、ここをクリックします Japan 変更 | サイトマップ MSDN Home > Visual Studio > Visual Studio 2008 Express Edition > 学習情報 > XNA > 01 ホーム Web インストール 製品の特徴 製品の機能 サポート 前のバージョン XNA Framework 01 赤坂玲音 ようこそ XNA の世界へ 本シリーズの目的 必要な環境 インストールするソフトウェア XNA Creators Club ソリューションとプロジェクト の作成 ゲームを起動する Xbox 360 の登録 Xbox 360 での実行 コードを書いてみる ゲーム ウィンドウ Game の拡張 更新速度の調整 画面の初期化 画像ファイルの描画 コンテンツ管理 ゲームの作成 ゲームの描画 コラム 参考資料 ようこそ XNA の世界へ これまで、家庭用ゲーム機のソフトウェアの開発というのは、趣味で開発している方や個人でのプログラマにとっては 手の届かない敷居の高いものでした。それは、プロフェッショナルのプログラマにとっても同じことです。ところが、 この状況は変わろうとしています。 Microsoft が提供する XNA Game Studio Express は、無償でダウンロードして使うことができる開発ツールで す。Windows PC があれば、誰でもダウンロードしてインストールすることができ、その場でゲーム開発ができます。 専用の開発用ハードウェアは必要ありません。 XNA Game Studio Express で開発したゲームは、Windows XPWindows Vista、そして Xbox 360 上で実行す ることができます。Windows 用のゲームは、開発したゲームを自由に配布して他の環境で実行させることも可能です が、Xbox 360 用のゲームの実行には XNA Creators Club に加入しなければなりません。 ここで重要なのは、XNA Game Studio Express Xbox 360 専用の開発環境ではないということです。XNA Game Studio が対象としている実行環境は XNA Framework と呼ばれる仮想環境です。 XNA Framework とは、.NET Framework と呼ばれる Windows アプリケーション開発で用いられている実行環境を 基盤に拡張した、ゲーム開発に特化した実行環境です。そのため .NET Framework の開発経験があれば、基礎的な機 能については知識を再利用することができます。 .XNA Framework の役割は、システムはハードウェアを隠蔽し、抽象的なコードを用いることで異なる環境下でも同じ プログラムを実行できるようにすることです。Windows Xbox 360 では、物理的なハードウェア構成やシステムの 作りが大きく異なります。そこで、プログラムを実行するときに XNA Framework が土台となってシステムの違いを吸 収してくれるのです。 01 Visual Studio ホーム Visual Studio Express Visual Studio Team System 基本情報 製品情報 購入情報 技術情報 パートナー情報 トレーニング情報 サポート情報 製品フィードバック ダウンロード情報 開発言語 Visual Studio .NET Framework ASP.NET スマート クライアント チーム開発 セキュリティ MSDN サブスクリプション Expression Silverlight Club Microsoft へ登録

Transcript of Visual Studio 2008 Express Editions - XNA Game Studio 入門...

Page 1: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

Silverlight をインストールするには、ここをクリックします Japan 変更 | サイトマップ

MSDN Home > Visual Studio > Visual Studio 2008 Express Edition > 学習情報 > XNA > 第 01 回

ホーム Web インストール 製品の特徴 製品の機能 サポート 前のバージョン

XNA Framework 第 01 回赤坂玲音 著

ようこそ XNA の世界へ本シリーズの目的必要な環境インストールするソフトウェアXNA Creators Clubソリューションとプロジェクトの作成ゲームを起動する

Xbox 360 の登録Xbox 360 での実行コードを書いてみるゲーム ウィンドウGame の拡張更新速度の調整画面の初期化

画像ファイルの描画コンテンツ管理ゲームの作成ゲームの描画

コラム参考資料

ようこそ XNA の世界へ

これまで、家庭用ゲーム機のソフトウェアの開発というのは、趣味で開発している方や個人でのプログラマにとっては手の届かない敷居の高いものでした。それは、プロフェッショナルのプログラマにとっても同じことです。ところが、この状況は変わろうとしています。

Microsoft が提供する XNA Game Studio Express は、無償でダウンロードして使うことができる開発ツールです。Windows PC があれば、誰でもダウンロードしてインストールすることができ、その場でゲーム開発ができます。専用の開発用ハードウェアは必要ありません。

XNA Game Studio Express で開発したゲームは、Windows XP、Windows Vista、そして Xbox 360 上で実行することができます。Windows 用のゲームは、開発したゲームを自由に配布して他の環境で実行させることも可能ですが、Xbox 360 用のゲームの実行には XNA Creators Club に加入しなければなりません。

ここで重要なのは、XNA Game Studio Express は Xbox 360 専用の開発環境ではないということです。XNAGame Studio が対象としている実行環境は XNA Framework と呼ばれる仮想環境です。

XNA Framework とは、.NET Framework と呼ばれる Windows アプリケーション開発で用いられている実行環境を基盤に拡張した、ゲーム開発に特化した実行環境です。そのため .NET Framework の開発経験があれば、基礎的な機能については知識を再利用することができます。

.XNA Framework の役割は、システムはハードウェアを隠蔽し、抽象的なコードを用いることで異なる環境下でも同じプログラムを実行できるようにすることです。Windows と Xbox 360 では、物理的なハードウェア構成やシステムの作りが大きく異なります。そこで、プログラムを実行するときに XNA Framework が土台となってシステムの違いを吸収してくれるのです。

■ 図 01

Visual Studio ホームVisual Studio Express

Visual Studio Team System

基本情報製品情報購入情報技術情報パートナー情報トレーニング情報サポート情報製品フィードバックダウンロード情報

開発言語

Visual Studio

.NET Framework

ASP.NET

スマート クライアントチーム開発セキュリティMSDN サブスクリプション

Expression

Silverlight

Club Microsoft へ登録

Page 2: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

ポート プロトコル 送受信1000 UDP 送信1001 TCP 送信3825 UDP 受信3835 UDP 受信

本稿で XNA Framework を体験していただくには、少なくとも Windows XP ServicePack 2 以降の Windows PC をご用意していただく必要があります。Xbox 360 があれば、XNA Creators Club に入会していただくことで、本稿のサンプルプログラムをXbox 360 上で実行し、体験していただくことができます。

また、ゲームの開発には様々な技術分野の応用が求められます。グラフィックスやサウンド、ネットワーク、セキュリティなど、ゲーム開発に必要なプログラムを、すべてゼロから作るのはとても困難です。XNA Framework は、ゲームの実行に必要な機能を部品として提供しています。XNA Framework が提供する豊富な機能や、XNA Game Studioのツールを利用することで、基本となる部分は開発ツールに任せて、私たちは目的とする処理の開発に集中することができるのです。

ゲーム開発は、簡単なものではありません。頭の中で想像したゲームを、実際に動く形にするには相当の努力と根気が必要です。しかし、プログラムの仕組みを理解し、思った通りのものが目の前で動いた時の感動は、開発者だけが味わうことのできる最高の喜びです。ぜひ、ゲーム開発に挑戦してください。

本シリーズの目的

本稿では、XNA Game Studio を使って XNA Framework ゲームを開発する方法についてご説明します。XNAFramework ゲームを開発するには、C# 言語と .NET Framework の基本的な知識に加えて、XNA Framework が提供するクラスライブラリの機能を理解する必要があります。また、ゲーム特有の開発方法や概念、グラフィックスやサウンドなどの扱い方なども理解しなければなりません。XNA Framework の機能と並行して、ゲーム特有の開発方法についても解説します。

本稿の解説対象は XNA Framework であり、その背景技術である .NET Framework や共通言語ランタイム、C# 言語については割愛させていただきます。C# 言語を使った .NET Framework アプリケーションの開発経験があれば問題ありません。

本シリーズでは、具体的なゲームの開発例としてマインスイーパをモデルとしたゲームを制作します。最初から 3 次元グラフィックスを扱うのは敷居が高くなるので、最初に画像ファイルを中心に 2 次元グラフィックスを使ったマインスイーパの開発を目指しましょう。ゲーム開発に必要な XNA Framework の様々な機能を最初にご紹介するので、XNAFramework 初心者の方でも順に読み進めていただければ無理なくゲーム作りを体験していただけるでしょう。

必要な環境

XNA Framework ゲームを開発するには、PC に必要なソフトウェアをインストールして環境を構築する必要があります。最初に、必要な環境の構築方法から、作成したゲームを Windows PC や Xbox 360 上で実行する方法をご説明します。

XNA Framework ゲームの開発は Windows XP SP2 以降、または Windows Vista がインストールされた PC 上で行います。Xbox 360 用のゲームを開発する場合でも、PC から Xbox 360 に対してデータを転送して実行します。Windows PC 用のゲーム開発であれば Windows PC 単体で開発とテストができますが、Xbox 360 用のゲームを開発するには、Windows PC と Xbox 360 本体に加えて、インターネットに接続されているネットワーク環境でWindows PC と Xbox 360 が互いに通信できる状態でなければなりません。

PC に標準のファイアウォールを除くサードパーティ製のセキュリティソフトがインストールされている場合、Xbox360 との通信のためにポートを開放しなければなりません。次のポートをブロックしないようにファイアウォールを設定してください。

インストールするソフトウェア

XNA Framework ゲームを開発するには Visual C# 2005 Express Edition と XNAGame Studio Express という 2 つの開発環境をインストールします。Visual C#2005 Express Edition は、一般の Windows アプリケーションなどにも用いられている開発ツールです。XNA Game Studio Express は、XNA Framework ゲーム開

発を専門とする Visual C#2005 Express Edition の機能の一部として組み込まれます。そのため、インストール

Page 3: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

は Visual C# 2005 ExpressEdition から行ってください。

XNA Framework ゲームの開発には、現時点では Visual C# 2005 Express Edition をベースとした環境しか用意されていないため、常に C# 言語を用います。Visual C# 2005 Express Edition の上位エディションである VisualStudio をインストールしている場合でも、XNA Game Studio Express を使うには Visual C# 2005 ExpressEdition をインストールしなければなりません。次のリンクからインストーラを入手して、開発用のシステムにインストールしてください。

Visual C# 2005 Express EditionXNA Game Studio Express

Visual C# 2005 Express Edition と XNA Game Studio Express のシステム要件については、上記の製品のページに詳細が記載されています。

XNA Framework ゲームの実行には、Shader Model 1.1 以上および、DirectX 9.0c に対応しているグラフィックカードが必要です。Shader Model 2.0 に対応しているグラフィックカードが推奨されまています。ゲーム用に構成された最近の PC であれば問題ありませんが、古いビジネス用の PC やノート PC の場合には注意が必要です。

XNA Creators Club

XNA Game Studio Express で作成した Xbox 360 用のゲームを、実際に Xbox 360 で実行するには XNACreators Club へ参加しなければなりません。XNA Creators Club に入会するには、Xbox Live のマーケットプレイスからメンバシップを購入します。メンバシップは、4 カ月 4,800 円と、1 年 9,800 円のどちらかを選択できます。開発に自信のない方は、最初は Windows PC 上で Windows 用のゲーム開発を体験していただいてからでも遅くはありません。XNA Game Studio Express で作成した Windows 用のゲームを Xbox 360 用のゲームに移植する作業は、驚くほど簡単です。

http://creators.xna.com/

ソリューションとプロジェクトの作成

Visual C# 2005 Express Edition と XNA Game Studio Express のインストールが終わったら、XNA GameStudio Express を起動してください。XNA Game Studio Express は、Visual C# 2005 Express Edition に統合されているため XNA Game Studio Express を起動すると、Visual C# 2005 Express Edition が起動しますが問題ありません。XNA Game Studio Express は、Visual C# 2005 Express Edition の追加機能としてインストールされています。

ゲームを開発するには、最初にプロジェクトを作成しなければなりません。プロジェクトには、プログラムのコードや、ゲームに使われる画像、様々な設定などが含まれています。新しくプロジェクトを作成するには [ファイル] メニューの [新しいプロジェクト] を選択します。

■ 図 02

[新しいプロジェクト] のダイアログが表示されるので、左側の [プロジェクトの種類] で [Visual C#] を選択し、右側の [テンプレート] で [Windows Game] を選択してください。Xbox 360 用のゲームを開発する場合は [Xbox 360Game] を選択しますが、この場では、まず Windows 上で手軽にプログラムの実行を体験してみましょう。

必要な項目を選択したら、プロジェクト名に適当な名前を入力し、プロジェクトを作成する場所を選択して [OK] ボタンを押します。下部に [ソリューション名] という入力項目があります。Visual C# を含め、Microsoft の開発環境である Visual Studio は、ソリューション単位でアプリケーション開発を管理することができます。ソリューションには複数のプロジェクトを含ませることができ、プログラムの部品となるプロジェクトを複数組み合わせて、大きなプログ

Page 4: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

ラムを作ることができます。プロジェクトが単体でもソリューションが必要になるため、プロジェクトを作成すると同時に新しいソリューションが作成されます。

■ 図 03

プロジェクトが作成されると、ダイアログが閉じられ XNA Game Studio Express のウィンドウに戻ります。画面右側の「ソリューション エクスプローラ」に注目してください。ここに、作成されたソリューションとプロジェクトの一覧が表示されます。この場では TestSolution という名前のソリューションで Sample01 という名前のプロジェクトを作成しています。ソリューションやプロジェクト名は任意なので、わかりやすい好きな名前を付けてください。

「ソリューション エクスプローラ」には、ソリューションに吹くまわれているプロジェクトと、プロジェクトに含まれているファイルなどが表示されています。作成したプロジェクトには、最初からプログラムに必要なソース ファイルと設定が含まれていいます。Game1.cs ファイルにはゲームそのもののコードが書かれており、Program.cs にはゲームを起動するためのコードが書かれています。試しに Program.cs をダブルクリックして開いてみてください。

■ 図 04

Page 5: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

図 04 のように、画面上にコードが表示されます。これが Program.cs ファイルに書かれているプログラムのコードです。プログラムのコードは単純なテキストなので、テキスト エディタを使って編集することができます。Windows 標準のメモ帳などでも編集は可能ですが、XNA Game Studio Express のエディタであれば、書いているプログラムの内容を理解し、入力を支援する機能があるので便利です。

ゲームを起動する

作成した「Sample01」プロジェクトは、そのままでも実行することができます。プログラミング言語によって書かれたプログラムは、テキストのままでは実行できません。作られたコードを実行できる形式に変換し、ゲームに必要な画像や音楽などのデータをパッケージ化しなければなりません。プログラムを実行するには [ビルド] メニューの [ソリューションのビルド] を選択してください。

■ 図 05

[ソリューションのビルド] を選択するとコンパイルが開始され、設定に基づいて実行可能ファイルが生成されます。ソース ファイルに誤りがある場合は、エラーが報告されてビルドが中断されます。 [ソリューションのビルド] を選択すると、ソリューション内のすべてプロジェクトがビルドされますが、「ソリューション エクスプローラ」上のプロジェクトを選択して、右クリックで表示されるメニューの [ビルド] を選択することで、プロジェクト単位でビルドすることも可能です。

エラーが発生しなければビルドは成功です。プロジェクトのフォルダ内にある bin フォルダを辿っていけば、生成された実行ファイルを確認できます。生成したゲームをファイルから実行することも可能ですが、開発中は XNA GameStudio Express から直接実行することができます。 [デバッグ] メニューの [デバッグ開始] を選択してください。

■ 図 06

[デバッグ開始] 実行した場合は、実行時に問題が発生すると、どのコードによって問題が発生したのかを追跡することができます。通常、開発中はプログラムの動作確認を何度も行うため、開発段階のゲームのテスト起動は [デバッグ開始] から行います。

■ Sample01 実行結果

作成したプロジェクトをビルドして実行すると、何も表示しない空のウィンドウが表示されます。プロジェクトは、最初から XNA Game Studio Express によって自動的に生成されたソース ファイルにゲームを起動するコードが書かれているため、何もしないウィンドウが表示されたのです。

Page 6: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

Xbox 360 の登録

Xbox 360 上で作成した XNA Framework ゲームを実行するには、Xbox 360 でダウンロードした [XNA GameLauncher] を起動しなければなりません。Xbox 360 を起動してダッシュボードを表示し [ゲーム] ブレードの [ゲーム ライブラリー] を選択してください。

[マイ ゲーム] の中にある [XNA Game Launcher] を選択し [始める] で起動します。XNA Framework ゲームは、Xbox 360 によって実行されるのではなく、XNA Game Launcher 上で仮想的に実行されます。PC で開発したゲームを Xbox 360 で実行するには、最初に設定を行う必要があります。

[Settings] を選択し [Generate Connection Key] を選択してください。すると [Your new connection key is] の下に認証キーとなる 25 桁の英数字が表示されます。この認証キーを XNA Game Studio に入力することで、PC からXbox 360 にゲームを転送することができるようになります。

XNA Game Studio Express に戻って、メニューバーから [ツール] の [オプション] を選択してください。

■ 図 07

次に、表示された [オプション] ダイアログの左側のツリーから [XNA Game Studio Express] を選択します。

■ 図 08

画面に [Available Xbox 360 consoles to deploy to] リストが表示されます。このリストに、XNA の実行テストを行う Xbox 360 を登録します。Xbox 360 を新しく追加するには、隣の [Add...] ボタンを押してください。

■ 図 09

Page 7: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

表示された [Add Xbox 360] ダイアログの [Xbox 360 Name] に、Xbox 360 を識別するわかりやすい任意の名前を入力し、 [Connection Key] に、先ほど Xbox 360 の XNA Game Launcher から取得した認証キーを正しく入力します。

キーを入力すると [Test Connection] ボタンが有効になります。このボタンを押すと、対象の Xbox 360 に接続できるかどうかをその場でテストすることができます。ただし、XNA Game Launcher がコンピュータとの接続を待機している状態でなければ、Xbox 360 が反応を返しません。テストを行うために、XNA Game Launcher の [Connect toComputer] を選択して「Waiting for computer connection.」が表示されていることを確認してから [TestConnection] ボタンを押してください。

接続に成功したことを確認し、最後に [OK] ボタンを押して登録作業は終了です。

Xbox 360 での実行

Xbox 360 で実行するゲームは、Xbox 360 用のプロジェクトとして作成されなければなりません。Sample 01 と同じように Xbox 360 用のプロジェクトを作成してみましょう。メニューバーから [ファイル] の [新しいプロジェクト]を選択し、表示されたダイアログに表示されているリストの中から [Xbox 360 Game] を選択してプロジェクトを作成します。

■ 図 10

「Xbox 360 Game」プロジェクトが最初から保有しているファイルを見ると、「Windows Game」プロジェクトで生成されたファイルとほとんど同じであることが確認できます。Windows 用のプロジェクトであっても Xbox 360 用のプロジェクトであっても、システムに依存したプログラムが書かれている場合や、実行速度の違いによって発生する問題を除き、同じファイルをコピーするだけで互いに移植することができます。Windows 用のゲーム開発との違いは、Xbox 360 では .NET Framework に関連する機能が制限されていることと、プログラムの実行に配置と呼ばれるデータの転送作業が必要なことです。

「Windows Game」プロジェクトと同じように、「Xbox 360 Game」プロジェクトも最初からビルドして実行することができます。実行結果も同じで水色のゲーム画面を表示するだけですが「Xbox 360 Game」プロジェクトの [デバッグ] を選択すると、自動的に Xbox 360 に配置されて実行される点が異なります。

XNA Framework ゲームを Xbox 360 に配置して実行するには、Xbox 360 側で XNA Game Launcher の[Connect to Computer] を選択してコンピュータからの接続を待機している状態にしなければなりません。Xbox360 側が PC からの接続を待機している状態で Xbox 360 用のプロジェクトを実行すると、自動的に Xbox 360 への配置が行われ、Xbox 360 で実行されます。さらに、Xbox 360 でデバッグ中のゲームの中断や終了などを XNAGame Studio から操作することができます。デバッガを用いて、実行中の変数の値などを調べることも可能なので、Visual Studio を利用している開発者であれば、これまでの経験をそのまま XNA Framework ゲーム開発に生かすことができます。

コードを書いてみる

開発環境の整備、プロジェクトの作成、テスト方法を理解していただければ、いよいよ XNA Framework ゲームの開発に取り掛かることができます。作成したプロジェクトに含まれていたソース ファイルには、ゲームを起動するまでの基本的なコードが含まれていました。これは、多くの XNA Framework ゲーム開発に共通した、必ず書くだろう最初のコードが自動生成されているためです。XNA Framework を理解していれば、すぐに目的の作業に入れるので便利なの

Page 8: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

ですが複雑です。

自動生成されたコードは捨てて、全く新しいコードをゼロから書いてみましょう。必要のないコードをすべて削り取り、ゲームの起動に必要な最小限のコードから理解する必要があります。まず、XNA Game Studio Express によって自動生成された、Game1.cs と Program.cs ファイルを削除してしまいます。プロジェクトからファイルを削除するには、ファイル上で右クリックし [削除] を選択してください。ファイルが削除され、プロジェクトから対象のファイルが外されます。

■ 図 11

次に、新しいソース ファイルを作成します。新しい項目をプロジェクトに追加するには、プロジェクト上で右クリックして表示されたメニューから [追加] → [新しい項目] を選択します。

■ 図 12

[新しい項目の追加] ダイアログが表示されるので、 [テンプレート] の中から [コード ファイル] を選択し、下部の[ファイル名] に生成するソース ファイルの名前を入力して [追加] ボタンを押してください。 [コード ファイル] は何も書かれていない空の C# ソース ファイルを作成します。

■ 図 13

Page 9: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

作成された新しいファイルを開いてみてください。今度は何も書かれていないファイルであることが確認できます。これからは、何も書かれていないソース ファイルを作成し、テスト用のコードを入力してください。XNA Framework が提供する個々の機能の働きを、実際にコードで書いて、実行することで体験していただきます。

作成したソース ファイルに、XNA Framework ゲームを起動するために必要な最小限のコードを書きましょう。XNAFramework の学習の手始めとして、次のコードの意味を理解しなければなりません。

■ Sample02 Test.cs

using Microsoft.Xna.Framework;

public class Test{ static void Main(string[] args) { Game game = new Game(); game.Run(); }}

■ Sample02 実行結果

Sample 02 の Test.cs を、作成したソース ファイルに書き写してください。たった 10 行程度のプログラムですが、Sample 01 と同じようにゲームを起動することができます。Sample 01 との違いは、ウィンドウに表示される画面の色だけです。プロジェクト作成時に自動生成されたコードには、画面を水色でクリアするコードが書かれていましたが、Sample 02 では画面をクリアするコードは何も書かれていないため、ゲームのデフォルトの色で塗りつぶされています。

これ以上コードを削ることに意味はないでしょう。たとえば、次のように書くことで行数を減らすことも可能ですが、これは書き方の問題です。

public class Test{ static void Main(string[] args) { (new Microsoft.Xna.Framework.Game()).Run(); }}

上記のコードの実行結果は Sample 02 と同じです。しかし、この場の目的は行数を少なくすることではなく、コードの意味を理解するためにシンプルにすることです。

Sample 02 の Test.cs ファイルに書かれているコードが行っている処理は極めて単純です。それは、新しいゲームの

Page 10: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

生成と、生成したゲームの実行です。1 つの XNA Framework ゲームは、Microsoft.Xna.Framework.Game クラスのインスタンスに対応しています。

■Microsoft.Xna.Framework.Game クラス

public class Game : IDisposable

ゲームを起動するには、このクラスのインスタンスを生成しなければなりません。Sample02 では、最初に new 演算子を用いて Game クラスのインスタンスを生成しています。このクラスのコンストラクタはパラメータを受け取りません。

■Game クラスのコンストラクタ

public Game ()

Game を生成しただけでは、ゲームが実行されることはありません。ゲームを実行するには Run() メソッドを呼び出します。

■Game クラス Run() メソッド

public void Run ()

Run() メソッドが呼び出されると、ゲームの初期化が行われ、その後にゲームが起動します。Run() メソッドを呼び出すと、プログラムの制御はゲーム用のループに移行します。ゲームを終了するまで Run() メソッドから制御が戻ることはありません。

Sample 02 は、Game クラスのインスタンスを生成し Run() メソッドを呼び出すことでゲームを起動しているのです。しかし、Game クラスはゲームを実行するための基礎的な機能しか提供していないため、独自のゲームを開発するにはこのクラスを継承して、必要な機能を追加しなければなりません。具体的なゲームの開発については、後述します。

Game クラスは IDisposable インターフェイスを実装しているため、オブジェクトが不要になれば Dispose() メソッドを呼び出してリソースを解放するべきです。そのため、Run() メソッドから制御が戻され、ゲームが終了した時点で、次のように明示的に Dispose() メソッドを呼び出してください。

Game game = new Game();game.Run();game.Dispose();

または using 文を用いて自動的に Dispose() メソッドが呼び出されるように書くべきです。

using (Game game = new Game()){ game.Run();}

一般的な C# 言語の書き方では、こちらが使われるでしょう。

ゲーム ウィンドウ

Windows 用に開発された XNA Framework ゲームを実行すると、ゲーム ウィンドウが表示されます。しかし、Xbox360 ではウィンドウではなく画面全体がゲームになります。ウィンドウが表示されるかどうかは、ゲーム自体にとって大きな問題ではありません。ゲームにとって重要なのは、ゲームが実行されるシステムの画面に、目的のグラフィックスを描画することです。そのため、基本的にゲームがどのような形で表示されるかはシステムに依存する問題です。

しかし、利用者の利便性を考えれば、ウィンドウの存在を全く無視することはできません。Xbox 360 だけを対象としたゲーム開発では重要ではありませんが、Windows 用のゲームを XNA Framework で開発する場合、ある程度のウィンドウの制御も必要になるでしょう。たとえば、Xbox 360 の場合は、ウィンドウに枠が存在せず、利用者がウィンドウのサイズを変更するようなことはありません。しかし、Windows 用のゲームであれば、利用者がウィンドウのサイズを変更することを許可できます。

ゲームが実行されているシステムによって提供されるウィンドウは、Microsoft.Xna.Framework.GameWindow クラスで表されます。ゲーム ウィンドウに対する設定や操作は、このクラスのオブジェクトを通して行います。

■ Microsoft.Xna.Framework.GameWindow クラス

public abstract class GameWindow

このクラス自体は抽象クラスなので、直接インスタンスを生成することはできません。ウィンドウの実体は、実行されるシステムによって異なりますが、XNA Framework によって抽象化されているため、ゲームの開発者は異なるシステムのウィンドウを、抽象的な GameWindow オブジェクトとして操作することができるのです。GameWindow クラスのインスタンスは、Game クラスの Window プロパティから取得することができます。

■ Game クラス Window プロパティ

public GameWindow Window { get; }

基本的に、ゲーム ウィンドウの制御が必要になるのは Windows 用のゲームでしょう。Xbox 360 の場合は、Windows のようなウィンドウ枠を持たないため、Xbox 360 に存在しない機能に対する操作は無視されます。Windows のウィンドウにはタイトル バーがあり、タイトルバーの上にゲームの名前など、設定したテキストを表示することができます。しかし、Xbox 360 にはタイトル バーがないため、無視されてしまいます。ウィンドウのタイトルの設定や取得は Title プロパティから行うことができます。

■ GameWindow クラス Title プロパティ

public string Title { get; set; }

Title プロパティに任意の文字列を設定すると、指定した文字列がタイトル バー上にテキストで表示されます。通常は、ゲームの名前やバージョンの組み合わせを表示することになるでしょう。しかし、この機能は Windows のためのもので、Xbox 360 では無視されます。

Page 11: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

■ Sample03 test.cs

using Microsoft.Xna.Framework;

public class Test{ static void Main(string[] args) { using (Game game = new Game()) { GameWindow window = game.Window; window.Title = "XNA Game Sample"; game.Run(); } }}

■ Sample03 実行結果

Sample 03 は、Run() メソッドでゲームを開始する前に、Game オブジェクトの Window プロパティからGameWindow オブジェクトを取得して Title プロパティに文字列を設定しています。実行結果を見れば、ウィンドウのタイトル バーに設定した文字列が表示されていることを確認できます。

Windows 専用のゲームで、他の一般的な Windows アプリケーションのように、ウィンドウのサイズを利用者が自由に変更することを許可することもできます。ウィンドウ サイズの変更を許可するには AllowUserResizing プロパティに true を設定してください。

■ GameWindow クラス AllowUserResizing プロパティ

[DefaultValueAttribute(false)]public virtual abstract bool AllowUserResizing { get; set; }

このプロパティは、ウィンドウのサイズを利用者が変更することを許可するかどうかを表しています。このプロパティの値が true であれば、ウィンドウの境界線をドラッグしてウィンドウのサイズを自由に調整できます。ただし、多くのゲームにとってサイズの変更は都合の良いものではありません。ウィンドウのサイズが変更されてしまった場合は、ゲーム画面も動的にウィンドウ サイズに従って調整する必要があります。

現在のウィンドウの位置とサイズは ClientBounds プロパティから取得できます。

■ GameWindow クラス ClientBounds プロパティ

public virtual abstract Rectangle ClientBounds { get; }

このプロパティは、長方形領域の座標とサイズを表す Microsoft.Xna.Framework.Rectangle 構造体のオブジェクトを返します。

■ Microsoft.Xna.Framework.Rectangle 構造体

[TypeConverterAttribute("typeof(Microsoft.Xna.Framework.Design.RectangleConverter)")][SerializableAttribute]public struct Rectangle : IEquatable<Rectangle>

Rectangle 構造体は、長方形の左上隅の座標を表す、X 及び Y フィールドと、幅を表す Width フィールド、高さを表す Height フィールドを公開しています。

■ Rectangle 構造体 X フィールド

public int X

■ Rectangle 構造体 Y フィールド

public int Y

■ Rectangle 構造体 Width フィールド

public int Width

■ Rectangle 構造体 Height フィールド

public int Height

X フィールドには長方形の左側の X 座標、Y フィールドには上部の Y 座標が格納されています。Windows の場合、通常は画面の左上隅を原点 0 として、X 座標の値が増えるほど右に、Y 座標の値が増えるほど下に向かいます。Widthフィールドには、長方形の左端から右端までの幅が、Height には上から下までの高さが格納されています。これらの値を調べることで、ゲーム ウィンドウの幅と高さを取得することができます。Windows 用のゲームで、サイズ変更を許可している場合には必要になるでしょう。

利用者によってウィンドウのサイズが変更される場合、プログラムが事前にウィンドウ サイズの変更のタイミングを予測できません。ウィンドウのサイズが変更されると、GameWindow クラスは ClientSizeChanged イベントを発生させます。サイズが変更されたタイミングで何らかの処理を実行したい場合は、このイベントにデリゲートを追加します。

■ GameWindow クラス ClientSizeChanged イベント

public event EventHandler ClientSizeChanged

GameWindow は、自分自身のサイズが変更されると、ClientSizeChanged イベントに登録されているデリゲートを呼び出します。このタイミングで ClientBounds プロパティから Rectangle オブジェクトを取得すれば、最新のウィンドウのサイズを知ることができます。

■ Sample04 test.cs

using System;using Microsoft.Xna.Framework;

Page 12: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

public class Test{ static void Main(string[] args) { using (Game game = new Game()) { GameWindow window = game.Window; window.AllowUserResizing = true; window.ClientSizeChanged += delegate(object sender, EventArgs e) { window.Title = window.ClientBounds.ToString(); }; game.Run(); } }}

■ Sample04 実行結果

Sample 04 は、GameWindow オブジェクトの AllowUserResizing プロパティに true を設定し、ウィンドウ サイズの変更を許可しています。ClientSizeChanged イベントにデリゲートを追加し、ウィンドウのサイズが変更されると、ClientBounds プロパティが返す Rectangle オブジェクトの文字列表現をタイトル バーに表示させます。このプログラムを実行して表示されたウィンドウは、一般的な Widows アプリケーションと同じように境界線をドラッグすることでサイズを変更することができます。サイズを変更すると、タイトル バーに表示されているテキストが更新されることを確認してください。

Game の拡張

これまでは、ゲームの雛型である Game クラスのインスタンスを生成し、外部からプロパティやメソッド呼び出して、その機能を確認するだけでした。Game クラスは何もしない空のゲームを表すクラスなので、画面に何かを描画したり、入力に反応することはありません。新しいゲームを開発するには、Game クラスを継承した独自のクラスを作り、このクラスの中で Game クラスのメソッドをオーバーライドして機能を拡張していきます。

public class YourGameName : Game { ....

Game クラスは、画像ファイルや音楽データなど、ゲームの実行に必要なリソースの管理や、ゲーム画面の更新と描画といったサイクルの管理を統合しています。開発者は、ゲームの実行サイクルを Game クラスに委ねて、必要な部分だけを拡張してゲームを作れます。Game クラスは、ゲームの状態に応じて適切なタイミングで呼び出される protectedなメソッドをいくつか持っています。このメソッドをオーバーライドすることで、任意の処理をゲームに組み込むことができます。

ここで重要なのは Game クラスが管理しているゲームの流れを理解することです。Game クラスの各種メソッドは、ゲームが起動してから終了するまで、永遠と繰り返し続けているサイクル(ゲーム ループ)の中で呼び出されます。ゲームの初期化、更新、解放などのタイミングで呼び出されるメソッドをオーバーライドすることで、そのタイミングで実行しなければならないコードを実行することができるようになります。

まず、Game クラスを継承したクラスが提供するゲーム固有の機能は、コンストラクタによって初期化されるべきです。ただし、コンストラクタはインスタンス化とのとき呼び出されるものなので、この状態ではゲームが実行されていないことに注意してください。ゲームは Run() メソッドが呼び出されたときに起動します。ゲームが起動したときに初期化するべき内容は Initialize() メソッドをオーバーライドして記述します。

■ Game クラス Initialize() メソッド

protected virtual void Initialize ()

コンストラクタと Initialize() メソッドの違いは、ゲームが起動しているかどうかです。Initialize() メソッドが呼び出されるのは Run() メソッドが呼び出され後で、ゲームを開始するための初期化処理を担当します。メソッドをオーバーライドした場合は、必ず既定クラスのメソッドを最後に呼び出してください。

■ Sample05 test.cs

using Microsoft.Xna.Framework;

public class Test : Game{ public Test() { Window.Title = "コンストラクタ→"; }

protected override void Initialize() { Window.Title += "Initialize→"; base.Initialize(); }

static void Main(string[] args) { using (Game game = new Test()) { game.Window.Title += "Run()メソッド手前→"; game.Run();

Page 13: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

} }}

■ Sample05 実行結果

Sample 05 では、Run() メソッドによってゲームが起動された後に Initialize() メソッドが呼び出されることを確認するためのプログラムです。これまで Main() メソッドで Game クラスのインスタンスを作成していましたが、Sample 06 では新しく作成した Test クラスをインスタンス化し Game オブジェクトとして扱っています。Game クラスを継承している Test クラスのコンストラクタから、順に GameWindow の Title プロパティに文字列を追加して、プログラムが実行された順をタイトル バーに表示させています。

Initialize() メソッドはゲームの起動時に 1 度だけ呼び出されるメソッドです。その後、ゲームが開始されると、Game クラスの Update() メソッドと Draw() メソッドが繰り返し呼び出されます。Update() メソッドの役割は、ゲームのデータを更新し、ゲームの流れを制御することです。

■ Game クラス Update() メソッド

protected virtual void Update (GameTime gameTime)

正しく設計されたゲームは、ゲームが内部で保持ているデータと、ゲーム画面のコードを適切に分離しています。例えば、将棋にはゲームの流れを記録した棋譜が存在します。棋譜は将棋というゲームにおけるデータであり、見た目となる将棋盤や駒と分離しています。棋譜があればゲームを再現することができ、熟練の愛好家であれば将棋盤がなくても棋譜だけでプレイすることができます。Update() メソッドの役割は、将棋の例で考えると棋譜を更新する処理です。

Draw() メソッドの役割は、ゲームの状態に応じた画面を構築することです。Draw() メソッドは Update() メソッドの直後に呼び出され、Update() メソッドによって更新されたゲームの状態に従って描画し、ゲーム画面を最新の状態にします。将棋で例えると、棋譜に基づいて将棋盤の上に駒を並べる作業が Draw() メソッドの役割となります。

■ Game クラス Draw() メソッド

protected virtual void Draw (GameTime gameTime)

Draw() メソッドは、Game クラスが管理しているゲームのサイクルの中で、ゲームの画面を構築するべき瞬間に呼び出されます。ゲーム画面は、動き回るキャラクターや演出効果などでアニメーションが必要なため、絶えず画面を更新し続けなければなりません。Game クラスは、Update() メソッドと Draw() メソッドを連続的に呼び出すことで、ゲームの 1 フレームを構築します。これは、セル画のアニメーションに近い性質です。画面の更新が必要になったときに画面を再構築するのではなく、短い間隔で定期的に画面を更新し続けているのです。

Update() メソッドと Draw() メソッドのパラメータには、ゲーム時間を提供する GameTime クラスのオブジェクトが渡されます。このオブジェクトを用いることで、メソッドが呼び出されたタイミングを把握することができます。

■ Microsoft.Xna.Framework.GameTime クラス

public class GameTime

ゲームを起動してから、ゲームが停止していた時間を除く経過時間を表す TotalGameTime プロパティから、ゲームが停止していた時間も含めた現実の経過時間を表す TotalRealTime プロパティから取得することができます。

■ GameTime クラス TotalGameTime プロパティ

public TimeSpan TotalGameTime { get; set; }

■ GameTime クラス TotalRealTime プロパティ

public TimeSpan TotalRealTime { get; set; }

これらのプロパティを用いれば、ゲームを起動してからどの程度の時間が経っているのかを把握できます。TotalGameTime プロパティは、ゲームが中断されている時間はカウントされていません。これに対して、TotalRealTime は、ゲーム時間に関係なく、ゲームを起動してから現在までの現実の時間経過を表しています。

■ Sample06 test.cs

using Microsoft.Xna.Framework;

public class Test : Game{ private string title; protected override void Update(GameTime gameTime) { title = "Update=" + gameTime.TotalRealTime.ToString(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { Window.Title = title + ", Draw=" + gameTime.TotalRealTime.ToString(); base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

■ Sample06 実行結果

Page 14: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

Sample 06 は、Game クラスを継承した新しい Test クラスを作成し、この中で Update() メソッドと Draw() メソッドをオーバーライドしています。これらのメソッドは、ゲーム ループの中で連続的に何度も呼び出され続けます。Update() メソッドはゲームの更新、Draw() メソッドはゲーム画面に表示する 1 フレームを構築するためのメソッドで、適切なタイミングで自動的に呼び出されます。明示的に呼び出す必要はありません。

Run() メソッドによってゲームが起動すると、Test クラスの Update() メソッドと Draw() メソッドが連続的に呼び出されることが確認できます。Update() メソッド内では、title フィールドにパラメータから受け取った GameTimeオブジェクトの TotalRealTime プロパティから取得した値の文字列表現を代入しています。Draw() メソッド内では、同じようにパラメータで受け取った GameTime オブジェクトから、ゲームを起動してからの時間を取得して、titleフィールドと合わせてタイトル バーに設定しています。

Draw() メソッドの役割はゲームの描画処理ですが、このプログラムでは Draw() メソッドが連続的に呼び出されていることを確認するために、タイトル バーに経過時間を設定しているだけです。当然、このままでは画面には何も表示されません。正しくは、この Draw() メソッドの中に描画処理を記述しなければなりません。

更新速度の調整

Update() メソッドと Draw() メソッドの連続的な呼び出しは、無秩序なものではありません。必要であれば、ゲームを更新する時間間隔を調整することができます。デフォルトでは、Update() メソッドは 1 秒間に 60 回のペースで呼び出されています。このタイミングは、Game クラスの sFixedTimeStep プロパティに影響されます。

■ Game クラス IsFixedTimeStep プロパティ

public bool IsFixedTimeStep { get; set; }

IsFixedTimeStep プロパティは、Update() メソッドの呼び出しの間隔を固定するかどうかを設定します。この値がtrue であれば TargetElapsedTime プロパティに設定されている間隔で Update() メソッドを呼び出し続けることを表し、false であれば可能な限りの頻度で Update() メソッドを呼び出し続けます。デフォルトでは true に設定されているため、TargetElapsedTime に設定されている値の間隔で呼び出されます。

■ Game クラス TargetElapsedTime プロパティ

public TimeSpan TargetElapsedTime { get; set; }

例えば、このプロパティに 100 ミリ秒の間隔を表す TimeSpan オブジェクトを設定すれば、Update() メソッドの呼び出しは 1 秒間に 10 回となります。この回数は、完全にゲーム時間と同期します。1 秒間に 10 回 Update() メソッドを呼び出すゲームの場合、Update() メソッドが 10 回目に呼び出されたときのゲーム時間は 1 秒であることが想定されます。これに対して、IsFixedTimeStep が false の場合、ゲーム時間と Update() メソッドの呼び出し回数は同期しません。

どちらの設定でも Draw() メソッドは可能な限りの頻度で呼び出され続けます。しかし、Draw() メソッドがUpdate() メソッドによって調整されるゲームデータに基づいた描画処理を行っているのであれば、Draw() メソッドが呼び出されるタイミングは重要なものではありません。

■ Sample07 test.cs

using System;using Microsoft.Xna.Framework;

public class Test : Game{ private int num; public Test() { IsFixedTimeStep = true; TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 100); }

protected override void Update(GameTime gameTime) { num++; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { Window.Title = "回数=" + num + ", GameTime=" + gameTime.TotalGameTime.ToString() + ", RealTime=" + gameTime.TotalRealTime.ToString(); base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

■ Sample07 実行結果

Sample07 は、TargetElapsedTime プロパティの値を変更して Update() メソッドが呼び出される頻度を変更しています。Draw() メソッドでは、TotalGameTime と TotalRealTime の値を比較して、Update() メソッドを呼び出している回数とゲーム時間が同期していることを確認しています。TotalRealTime は、実際の経過時間なので Update()メソッドの影響は受けませんが、TotalGameTime は Update() メソッドが呼び出されたタイミングで更新されています。

Page 15: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

画面の初期化

いよいよ Draw() メソッドの本来の仕事であるグラフィックスの描画処理を行います。これまで起動したゲームには何も表示されませんでした。ゲームの画面に図形や画像を表示するには、Draw() メソッドをオーバーライドし、その中で適切な描画プログラムを記述しなければなりません。描画に必要なオブジェクトの取得はMicrosoft.Xna.Framework.GraphicsDeviceManager クラスによって行われます。

■ Microsoft.Xna.Framework.GraphicsDeviceManager クラス

public class GraphicsDeviceManager : IGraphicsDeviceService, IDisposable, IGraphicsDeviceManager

GraphicsDeviceManager クラスは、ゲームとゲームを描画するデバイスを接続し、描画に必要なオブジェクトの生成や破棄を管理してくれます。アプリケーションが、物理的なハードウェア構成を意識する必要はありません。XNAFramework が対象としているのは、高度な 3D グラフィックスを描画することができるゲーム用のデバイスに限られており、GraphicsDeviceManager は、ゲームが起動しているシステムの適切なデバイスを関連付けてくれます。

このクラスのコンストラクタには、描画処理を行う Game オブジェクトを指定します。

■ GraphicsDeviceManager クラスのコンストラクタ

public GraphicsDeviceManager (Game game)

game パラメータに、生成する GraphicsDeviceManager に関連付ける Game オブジェクトを指定します。通常は、Game クラスをインスタンス化した時、Run() メソッドを呼び出す前に GraphicsDeviceManager をインスタンス化します。Game を継承したクラスのコンストラクタで GraphicsDeviceManager をインスタンス化し、privateなフィールドに保存しておけばよいでしょう。

描画を行うには、GraphicsDeviceManager オブジェクトの GraphicsDevice プロパティを利用します。

■ GraphicsDeviceManager クラス GraphicsDevice プロパティ

public GraphicsDevice GraphicsDevice { get; }

このプロパティは、Microsoft.Xna.Framework.Graphics.GraphicsDevice クラスのオブジェクトを返します。このクラスを用いて、画面に表示するべきデータを描画することができます。GraphicsDeviceManager のインスタンスを生成しても、関連付けている Game オブジェクトが起動していない限り null を返すことがあるので注意してください。GraphicsDevice オブジェクトは、ゲーム起動後、Game クラスの Initialize() メソッドが呼び出される前に生成されます。

■ Microsoft.Xna.Framework.Graphics.GraphicsDevice クラス

public class GraphicsDevice : IDisposable

GraphicsDevice オブジェクトは、描画可能なデバイスを表現するオブジェクトです。このオブジェクトを取得することができれば、Draw() メソッド内で GraphicsDevice のメソッドを呼び出すことで、このオブジェクトに関連付けられている画面に対して描画することができます。GraphicsDevice は、多くのプロパティとメソッドを持ちますが、この場では画面を指定した色で塗りつぶす Clear() メソッドを使って、描画を体験してみましょう。

■ GraphicsDevice クラス Clear() メソッド

public void Clear (Color color)

このメソッドの color パラメータには、画面を塗りつぶす色を指定します。色はMicrosoft.Xna.Framework.Graphics.Color 構造体によって表すことができます。

■ Microsoft.Xna.Framework.Graphics.Color 構造体

public struct Color : IPackedVector<UInt32>, IEquatable<Color>

この構造体には、次のようなコンストラクタがあります。

■ Color 構造体のコンストラクタ

public Color (byte r, byte g, byte b)public Color (byte r, byte g, byte b, byte a)

色の表現には、コンピュータで一般的な赤、緑、青の三原色の強さの組み合わせに、不透明度を表すアルファ値を合わせた ARGB 方式が使われています。コンストラクタに渡すパラメータの r には赤要素、g には緑要素、b には青要素の強さを表す値を指定します。それぞれの色要素は 0 が一番弱く、255 が一番強いことを表します。全ての値が 0 であれば完全な黒、全ての値が 255 であれば完全な白を表します。a パラメータにはアルファ値を指定します。アルファ値は 0 であれば完全な透明、255 であれば完全な不透明であることを表します。

色要素は、Color 構造体のプロパティ A、R、G、B から取得することも可能です。A プロパティはアルファ値を、Rプロパティは赤要素、G プロパティは緑要素、B プロパティは青要素を表しています。

■ Color 構造体 A プロパティ

public byte A { get; }

■ Color 構造体 R プロパティ

public byte R { get; }

■ Color 構造体 G プロパティ

public byte G { get; }

■ Color 構造体 B プロパティ

public byte B { get; }

値を指定して細かく色の調整を行いたい場合は、Color 構造体のコンストラクタから目的の色を表すオブジェクトを生成します。しかし、一般的に用いられる代表的な色は Color 構造体の static なプロパティとして用意されています。例えば、赤色の Color オブジェクトが必要な場合は Color.Red 空取得することができます。

■ Sample08 test.cs

Page 16: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;

public class Test : Game{ private GraphicsDeviceManager graphics; public Test() { graphics = new GraphicsDeviceManager(this); }

protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.Pink); base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

■ Sample08 実行結果

Sample 08 では、Test クラスのコンストラクタで GraphicsDeviceManager をインスタンス化し、Draw() メソッドで GraphicsDeviceManager の GraphicsDevice プロパティから取得できる GraphicsDevice オブジェクトを通して画面をピンク色に塗りつぶしています。Clear() メソッドは、パラメータに指定された Color オブジェクトの値に従って画面を塗りつぶします。

画像ファイルの描画

XNA Framework は 3 次元グラフィックスのゲームを対象としているため、GraphicsDevice オブジェクトに 2 次元グラフィックスの描画の考え方はありません。GraphicsDevice オブジェクトによって画面に描画するのは、プリミティブと呼ばれる単純なポリゴンの組み合わせとなります。プリミティブは、3 次元空間上の頂点をいくつか組み合わせたもので、頂点を線や三角形で頂点を結びつけて描画することができます。GraphicsDevice によるプリミティブをベースとした描画方式で 2 次元ベースのゲームを開発するには、3 次元グラフィックスの中で平面を使って擬似的に 2次元を装います。

この場では、比較的簡単な 2 次元グラフィックスの描画を先に体験していただきます。XNA Framework といえば、リッチな 3 次元グラフィックを使ったゲームを想像されるかもしれませんが、画像ファイルを組み合わせた 2 次元グラフィックスをベースとしたゲームの開発も可能です。画像ファイルを読み込んで画面に描画するには、Microsoft.Xna.Framework.Graphics.SpriteBatch クラスを使います。このクラスによって描画された画像の領域をスプライトとも呼びます。

■ Microsoft.Xna.Framework.Graphics.SpriteBatch クラス

public class SpriteBatch : IDisposable

このクラスのコンストラクタには、スプライトを描画する GraphicsDevice オブジェクトを指定します。

■ SpriteBatch クラスのコンストラクタ

public SpriteBatch (GraphicsDevice graphicsDevice)

SpriteBatch オブジェクトの生成には、GraphicsDevice をコンストラクタに渡さなければならないため、例えばGame クラスからオーバーライドした Initialize() メソッドなどで SpriteBatch オブジェクトを生成します。

Grame クラスからオーバーライドした Draw() メソッド内で、生成した SpriteBatch オブジェクトを用いて画像ファイルをスプライトとして描画することができます。スプライトを描画するには、最初に Begin() メソッドを呼び出して描画の準備を行う必要があります。Begin() メソッドは、スプライトの描画を行うために GraphicsDevice オブジェクトの描画設定を変更します。

■ SpriteBatch クラス Begin() メソッド

public void Begin ()

Begin() メソッドの後にスプライトの描画処理を行う、処理が終了した時点で End() メソッドを呼び出さなければなりません。このメソッドによって、GraphicsDevice の状態を Begin() メソッドを呼び出す前の状態に復元します。

■ SpriteBatch クラス End() メソッド

public void End ()

Page 17: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

End() メソッドは Begin() メソッドと対にして利用します。Begin( ) メソッドを呼び出した後、必ず End() メソッドでスプライトの描画を終了してください。

Begin() メソッドが呼び出された後、End() メソッドが呼び出される前の間に、SpriteBatch クラスの Draw() メソッドを用いてスプライトを描画することができます。

■ SpriteBatch クラス Draw() メソッド

public void Draw ( Texture2D texture, Vector2 position, Color color)

最初の texture パラメータには、スプライトとして描画される画像を表すMicrosoft.Xna.Framework.Graphics.Texture2D クラスのオブジェクトを、第 2 パラメータには画面のどこに描画するかを表す Microsoft.Xna.Framework.Vector2 構造体のオブジェクトを指定します。最後の color パラメータは、描画される画像に合成する色です。完全な白を表す Color.White を指定すれば画像本来の色で描画されます。

描画される画像は、Texture2D クラスのオブジェクトです。このクラスを用いることで、任意のフォーマットによる色情報を並べたビットマップを提供することができます。BMP 拡張子の Windows ビットマップや、インターネットで標準的な JPEG、PNG などのファイルが表す画像は、すべて Texture2D として読み込むことができます。Texture2Dオブジェクトによって 3 次元グラフィックスとして貼り付けられる画像のことを、テクスチャと呼びます。

■ Microsoft.Xna.Framework.Graphics.Texture2D クラス

public class Texture2D : Texture

Windows 用の XNA Framework ゲームであれば、ファイルから直接読み込むことができます。ファイルからTexture2D オブジェクトを生成するには、Texture2D クラスの static な FromFile() メソッドを使います。このメソッドは、Xbox 360 用のプロジェクトでは使えません。

■ Texture2D クラス FromFile() メソッド

public static Texture2D FromFile ( GraphicsDevice graphicsDevice, string filename)

graphicsDevice には、読み込んだ画像をテクスチャとして描画する GraphicsDevice オブジェクトを指定します。filename には、読み込む画像ファイルのパスを表す文字列を指定します。このメソッドが成功すれば、戻り値からTexture2D オブジェクトを得ることができます。

Texture2D を Draw() メソッドで描画するとき、テクスチャを描画する座標を Vector2D 構造体のオブジェクトで指定します。この構造体は、X 座標と Y 座標からなる 2 次元空間上の 1 点を表すことができます。

■ Microsoft.Xna.Framework.Vector2 構造体

[TypeConverterAttribute("typeof(Microsoft.Xna.Framework.Design.Vector2Converter)")][SerializableAttribute]public struct Vector2 : IEquatable<Vector2>

この構造体には、次のようなコンストラクタがあります。

■ Vector2 構造体のコンストラクタ

public Vector2 (float value)public Vector2 (float x, float y)

value には、X 座標と Y 座標の両方を初期化する値を指定します。オーバーロードされている x パラメータと y パラメータを渡すコンストラクタは、それぞれの値で X 座標と Y 座標を初期化します。コンストラクタから指定した値は Xフィールドと Y フィールドに格納されています。

■ Vector2D 構造体 X フィールド

public float X

■ Vector2D 構造体 Y フィールド

public float Y

Draw() メソッドは、画面の左上隅を原点 (0, 0) とし、Vector2D が表す座標がテクスチャの左上隅となるようにTexture2D を描画します。

■ Sample09 test.cs

using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;

public class Test : Game{ private GraphicsDeviceManager graphics; private Texture2D texture;

public Test() { graphics = new GraphicsDeviceManager(this); }

protected override void Initialize() { texture = Texture2D.FromFile(graphics.GraphicsDevice, "test.jpg"); base.Initialize(); }

protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.White);

Vector2 pt = new Vector2(0, 0); SpriteBatch sprite = new SpriteBatch(graphics.GraphicsDevice); sprite.Begin(); sprite.Draw(texture, pt, Color.White); sprite.End();

base.Draw(gameTime);

Page 18: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

}

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

■ Sample09 実行結果

Sample09 は、実行ファイルと同じディレクトリにある test.jpg ファイルを読み込んで画面に表示するプログラムです。Initialize() メソッドで、ゲームが起動されたときに、描画に必要な SpriteBatch オブジェクトと Texture2D オブジェクトをインスタンス化し、private フィールドとして保存しています。Test クラスの Draw() メソッドでは、SpriteBatch オブジェクトの Draw() メソッドを呼び出して、事前に読み込んでおいたテクスチャを描画しているだけです。

Vector2D オブジェクトで座標を指定した Draw() メソッドによって描画されたスプライトは、テクスチャの本来の幅と高さで表示されます。描画するスプライトの幅や高さを、Texture2D のサイズに関係なく、任意の幅と高さに伸縮して描画したい場合は、次のオーバーロードされた Draw() メソッドを使います。

■ SpriteBatch クラス Draw() メソッド

public void Draw ( Texture2D texture, Rectangle destinationRectangle, Color color)

texture パラメータと color パラメータは同じです。異なるのは Vector2D を指定していた第 2 パラメータがRectangle 型の estinationRectangle になっている点です。この Rectangle オブジェクトは、スプライトを描画する長方形領域を表しています。テクスチャは、destinationRectangle パラメータが表す長方形に伸縮されます。

Texture2D オブジェクトが表す画像の本来の幅と高さは Width プロパティと Height プロパティから取得することができます。

■ Texture2D クラス Width プロパティ

public int Width { get; }

■ Texture2D クラス Height プロパティ

public int Height { get; }

Width プロパティは幅を、Height プロパティは高さ、それぞれピクセル単位で返します。

■ Sample10 test.cs

using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;

public class Test : Game{ private GraphicsDeviceManager graphics; private Texture2D texture;

public Test() { graphics = new GraphicsDeviceManager(this); }

protected override void Initialize() { texture = Texture2D.FromFile(graphics.GraphicsDevice, "test.jpg"); base.Initialize(); }

protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.White);

Rectangle rect = new Rectangle(50, 20, texture.Width / 2, texture.Height / 2); SpriteBatch sprite = new SpriteBatch(graphics.GraphicsDevice); sprite.Begin(); sprite.Draw(texture, rect, Color.White); sprite.End();

base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }

Page 19: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

}

■ Sample10 の実行結果

Sample10 は、Rectangle オブジェクトで指定した長方形領域に伸縮して画像を描画するプログラムです。Rectangleオブジェクトに指定している幅と高さは、Texture2D オブジェクトの Width プロパティと Height プロパティが返した値から 2 で割った値となります。実行結果を見れば、本来の画像のサイズの半分の幅と高さで描画されていることが確認できます。

コンテンツ管理

Xbox 360 では、Texture2D クラスの FromFile() メソッドを用いてテクスチャを読み込むことができません。XNAFramework では、ゲームプログラムの本体とは別に配置される、画像ファイルのようなデータをリソースと呼んでいます。リソースはゲームの実行に重要な要素ですが、ファイル単位で入出力を行っていは効率が悪いため、XNAFramework がリソースの管理を統合する機能を提供しています。通常、XNA Framework ゲームで使用する画像などは、この仕組みに従います。

ファイル単位で画像や音声を扱う場合、ゲーム自体がファイル フォーマットに対応しなければならず、場合によっては読み込み時にシステムに最適化するための変換処理を行わなければなりません。また、多くのデータ ファイルはゲームに特化しているものではなく、ゲームには不要な情報が含まれていたり、ゲームに適していない場合もあります。XNAFramework のコンテンツ管理機能は、こうした問題を解決します。XNA Game Studio によってゲームがビルドされる時点で、関連付けられているリソースをゲームに最適化されたデータに変換し、ゲーム実行時には、データの元のファイル フォーマットを意識することなく読み込むことができるようになります。

リソースの元となっているファイルから、ビルド時に変換処理を行い、ゲームに最適化された形式のデータを生成し、実行時にデータを読み込んでゲームで使用するリソースの流れをコンテンツ・パイプラインと呼びます。

実行時にリソースを読み込むには、XNA Game Studio で事前にファイルをビルドしなければなりません。Texture2Dとして読み込む画像ファイルをプロジェクトに関連付けるのは簡単です。プロジェクトに画像ファイルを追加し [プロパティ] から [XNA Framework Content] を "true" に設定します。 [Asset Name] は、ビルド時にゲーム用に最適化されたデータとして生成されるファイルの名前です。この名前からリソースを読み込むことができます。任意の名前で構いませんが、この場では "test" という名前を入れます。 [Content Importer] と [Content Processor] は、元のファイルを読み込み、加工や変換を行うプログラムの選択です。 [Content Importer] には "Texture - XNAFramework" を、 [Content rocessor] には "Texture (Sprite, 32dpp) - XNA Framework" を選択してください。

リソースを含むプロジェクトをビルドすると、実行ファイルが生成されるフォルダに [Asset Name] で指定した名前のXNB 拡張子のファイルが生成されています。これが、ビルド時に元の画像ファイルから生成されたデータです。生成した XNB ファイルを実行時にオブジェクトとして取得するには icrosoft.Xna.Framework.Content.ContentManagerクラスを使います。このクラスは、ゲームに関連付けられているリソースを統合管理してくれています。

■ Microsoft.Xna.Framework.Content.ContentManager クラス

public class ContentManager : IDisposable

リソースを読み込むには、ゲームが起動する前に ContentManager をインスタンス化しておく必要があります。このクラスのコンストラクタには、IServiceProvider インタフェースを実装するオブジェクトを渡します。

■ ContentManager クラスのコンストラクタ

public ContentManager ( IServiceProvider serviceProvider)

このコンストラクタの serviceProvider パラメータに指定するオブジェクトは、ContentManager が要求する型のオブジェクトを提供できなければなりません。少なくとも、テクスチャを読み込む場合はMicrosoft.Xna.Framework.Graphics.IGraphicsDeviceService 型のオブジェクトをサービスとして提供しなければなりません。通常は Game クラスの Services プロパティが返す GameServiceContainer オブジェクトを指定します。

■ Game クラス Services プロパティ

public GameServiceContainer Services { get; }

Services プロパティは、Game クラスが提供する任意の数のサービスを格納する入れ物としての機能を持つMicrosoft.Xna.Framework.GameServiceContainer クラスのオブジェクトを返します。このクラス自身がIServiceProvider インタフェースを実装しているため、Services プロパティの値を ContentManager クラスのコンストラクタに渡すことができます。

■ Microsoft.Xna.Framework.GameServiceContainer クラス

public class GameServiceContainer : IServiceProvider

Page 20: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

ContentManager を使ってデータを読み込むタイミングは、ゲームが起動し、初期化が適切に行われた以降であれば任意です。ContentManager からリソースを読み込むには Load() メソッドを使います。

■ ContentManager クラス Load() メソッド

public virtual T Load<T> ( string assetName)

型パラメータ T には、読み込むデータの型を指定します。画像を読み込む場合は Texture2D 型のオブジェクトとして読み込むので T には Texture2D を指定します。assetName パラメータには、XNA Game Studio の [AssetName] で設定した名前を指定します。ContentManager は、指定した名前に対応するファイルから、目的のリソースを読み込みます。

■ Sample11 test.cs

using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.Graphics;

public class Test : Game{ private GraphicsDeviceManager graphics; private ContentManager content; private Texture2D texture;

public Test() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); }

protected override void Initialize() { texture = content.Load<Texture2D>("test"); base.Initialize(); }

protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.White);

SpriteBatch sprite = new SpriteBatch(graphics.GraphicsDevice); sprite.Begin(); sprite.Draw(texture, new Vector2(0, 0), Color.White); sprite.End();

base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

Sample11 の実行結果は Sample09 と同じです。読み込んだ画像を、SpriteBatch オブジェクトの Draw() メソッドで描画しているだけです。しかし、Texture2D クラスの FromFIle() メソッドを使って JPEG ファイルから直接読み込んでいるのではなく、ContentManager オブジェクトを用いて管理されたリソースとして読み込んでいる点が異なります。

ContentManager からリソースを読み込むタイミングは任意ですが、テクスチャなどのグラフィックスに関連するリソースの読み込みは、通常は Game クラスの LoadGraphicsContent() メソッドをオーバーライドし、このメソッドが呼び出されたタイミングで行います。このメソッドは Initialize() メソッドの直後や、デバイスがリセットされ再度リソースを読み込む必要がある場合に呼び出されます。

■ Game クラス LoadGraphicsContent() メソッド

protected virtual void LoadGraphicsContent ( bool loadAllContent)

loadAllContent は、全てのリソースが読み込まれる必要がある場合は true。そうでなければ false が格納されています。ContentManager から読み込むリソースであれば、通常は loadAllContent が true の場合にのみ読み込みます。

Game クラスには、LoadGraphicsContent() メソッドに対になる形で UnloadGraphicsContent() も存在します。このメソッドは、グラフィックスに関連するリソースが解放される必要がある時に呼び出されます。このメソッドをオーバーライドし、ContentManager から読み込んだリソースを解放するべきです。

■ Game クラス UnloadGraphicsContent() メソッド

protected virtual void UnloadGraphicsContent ( bool unloadAllContent)

unloadAllContent は、すべてのリソースが解放される必要がある場合は true。そうでなければ false が格納されています。やはり、ContentManager から読み込んだリソースは、LoadGraphicsContent() メソッドの場合と同じようにunloadAllContent が true の時に解放するべきです。

Texture2D クラスは IDisposable インターフェイスを実装しているので Dispose() メソッドで解放することができますが、ContentManager クラスの Unload() メソッドを呼び出すことで、ContentManager から読み込んだ全てのリソースを一度に解放することができます。

■ ContentManager クラス Unload() メソッド

public virtual void Unload ()

例えば、マルチ ディスプレイ環境の Windows で実行されているゲームでウィンドウが別のディスプレイに移動されたときなど、ゲーム画面を描画しているデバイスが変更されたときに呼び出されます。デバイスがリセットされると、最初に UnloadGraphicsContent() メソッドが呼び出され、既存のリソースをすべて解放します。その後、LoadGraphicsContent() メソッドが呼び出されるので、再度リソースを読み込みます。

■ Sample12 test.cs

Page 21: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.Graphics;

public class Test : Game{ private GraphicsDeviceManager graphics; private ContentManager content; private Texture2D texture;

public Test() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); }

protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) texture = content.Load<Texture2D>("test"); }

protected override void UnloadGraphicsContent(bool unloadAllContent) { if (unloadAllContent) content.Unload(); }

protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.White);

SpriteBatch sprite = new SpriteBatch(graphics.GraphicsDevice); sprite.Begin(); sprite.Draw(texture, new Vector2(0, 0), Color.White); sprite.End();

base.Draw(gameTime); }

static void Main(string[] args) { using (Game game = new Test()) game.Run(); }}

Sample12 は、GraphicsDevice オブジェクトに関連付けられるリソースの読み込みと解放に対応したプログラムです。LoadGraphicsContent() メソッドをオーバーライドし、テクスチャの読み込みをこのメソッドの中で行っています。また、UnloadGraphicsContent() が呼び出されると ContentManager の Unload() を呼び出して、読み込んだテクスチャを解放しています。実行結果の見た目は Sample 11 と同じですが、ディスプレイ環境の変更に対応することができるという点で異なります。

実は、これまでのテクスチャを用いたプログラムは、マルチ ディスプレイ環境下でゲームを描画しているウィンドウを別のディスプレイに移動させると実行時例外が発生しました。マルチ ディスプレイ環境の Windows では、ゲームを描画しているウィンドウが別のディスプレイに移されると、描画するデバイスを表している GraphicsDevice オブジェクトも変更しなければなりません。GraphicsDeviceManager は、Game オブジェクトのウィンドウが表示されているディスプレイが変更されると、新しい GraphicsDevice オブジェクトを生成します。これに合わせて、Texture2D も新しいデバイス用に読みなおす必要があるのです。

ゲームの作成

本稿では、実践的なゲームの例としてマインスイーパの開発を体験していただきます。XNA Framework が提供する機能は、ゲーム ループの管理やゲームの描画やコントーラからの入力など、比較的ハードウェアに近い処理や、リソースの管理など、多くのゲーム開発で汎用的に利用可能なインフラストラクチャでしかありません。どのようなゲームの開発でも、そのゲーム固有のデータやアルゴリズムは自分で書かなければなりません。

どのようなゲームでも、ゲームの状態を表すデータが必要になります。マインスイーパであれば、ゲーム画面に表示するマス目の数や、マスの上に地雷があるかどうかなどが重要な情報となります。Game クラスでは、マインスイーパの状態を表すオブジェクトを保有し、そのオブジェクトが提供する情報に従って Draw() メソッド内で画面に描画するという手順になります。そこで、まずはマインスイーパの状態を表すデータクラスを作成してみましょう。この場では、仮に MineField という名前のクラスで作成します。

■ MineField クラス

public class MineField

まずは、MineField クラスがどのような機能を提供するのかを考える必要があります。マインスイーパの性質から、ゲームの領域は水平方向と垂直方向に並べられたマス目と、その上に地雷が存在するかどうかが重要になります。マス目の数は固定せずに、自由に設定できる方が柔軟性があるので、これも変数にしましょう。このことから MineField クラスは、次の 2 つのプロパティを公開するべきです。

■MineField クラス Columns プロパティ

public int Columns { get; }

■MineField クラス Rows プロパティ

public int Rows { get; }

Columns は垂直方向のマス目の数(列数)を表し、Rows は垂直方向のマス目の数(行数)を表します。インスタンス生成後に、これらの値を変更できなければならないという要求が無ければ読み取り専用にするべきでしょう。

加えて、指定したマスに地雷があるかどうかを調べなければなりません。地雷があるかどうかであれば bool 型の値で表現することができますが、地雷の状態が複数存在する特殊なデータ表現が必要な場合は列挙型を用いるべきです。ゲームという性質を考えれば柔軟性のある列挙型にするべきかもしれませんが、本稿では bool 型で表現します。

どのマスに地雷があるかどうかを調べるには、マスの座標を指定しなければなりません。これは、列番号と行番号から判断することができます。メソッドとして作成しても構いませんが、この場ではインデクサを使うことにしましょう。こうすることによって MineField オブジェクトがマインスイーパのマス目そのものを表す配列のように扱うことができ

Page 22: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

ます。

■MineField クラスのインデクサ

public bool this[int cols, int rows] { get; set; }

cols には列番号を、rows には行番号を指定します。指定した座標のマスに地雷がある場合は true を返すという仕組みになります。地雷の設置は、インスタンス生成後にも行える必要があるため、値の設定も許容しています。

マインスイーパの地雷原を表現する目に必要な最小限の情報はこれだけです。あとは、このオブジェクトの操作で頻繁に用いられるような処理や機能をメソッドとしてまとめておくと便利になります。たとえば、すべてのマスをクリアする Clear() メソッドや、乱数を用いてランダムに地雷を配置する andom() メソッドなどを用意します。

■MineField クラス Clear() メソッド

public void Clear()public void Clear(bool mine)

パラメータを受け取らない Clear() メソッドは、すべてのマスを地雷のない状態でクリアし、mine パラメータを受け取るメソッドは、ture であれば全てを地雷で、そうでなければ地雷のない状態でクリアするものとします。

Random() メソッドは、指定した数の地雷をマスの中に適当に配置します。

■MineField クラス Random() メソッド

public void Random(int mines)

mines には、設置する地雷の数を指定します。この値に指定された数だけ、ランダムで地雷を設置します。このメソッドがあれば、ゲームの初期化やリセットが容易になります。

最後に、指定したマスの周囲にいくつ地雷が存在するかどうかを返す GetAdjacentMines() メソッドを作成しておきます。

■MineField クラス GetAdjacentMines() メソッド

public int GetAdjacentMines(int cols, int rows)

cols と rows に、対象のマスを指定します。このメソッドは、指定されたマスの周囲八方にある地雷の数を返します。Game クラスの Draw() メソッド内では、繰り返し文を使って、全てのマスを対象にこのメソッドを呼び出し、周囲の爆弾の数に従って描画するテクスチャを決定することができます。

ゲームの描画

ゲームのデータを用意することができれば、次は Game クラスの Draw() メソッドを用いた描画です。前述したように、ゲームの開発では Update() メソッド内でゲームデータの制御を行い、Draw() メソッドでゲームのデータを描画するという手順になります。MineField クラスのオブジェクトを、コンストラクタまたは Initialize() メソッドで作成し、Draw() メソッドで対応するマス目に対応する画像を個別に描画していきます。このとき、事前にリソースとしてマス目を表す画像を用意しておきます。

本稿のサンプルで最低限必要なのは、地雷が配置されていないマスと、地雷が配置されているマス、そして、1 から 8までの周囲の地雷の数が描かれているマスの画像ファイルです。こうした画像ファイルを個別に扱っていては柔軟性が失われるので、マインスイーパ用のテクスチャを管理する ImageManager クラスを作成し、この中でリソースの読み込みや検索を行うことにしましょう。

■ImageManager クラス

public class ImageManager : IDisposable

このクラスのコンストラクタで、ContentManager オブジェクトを受け取り、必要なリソースを読み込みます。

■ImageManager クラスのコンストラクタ

public ImageManager(ContentManager contentManager)

ここで開発する ImageManager は、コンストラクタが呼び出された時点で contentManager パラメータに渡されたContentManager オブジェクトの Load() メソッドを用いてテクスチャを読み込みます。

マインスイーパのマスは、すべて同じ幅と高さである必要があるため、テクスチャは個別の画像ファイルから読み込みますが、ImageManager クラスが提供するテクスチャは、すべて同じ幅と高さであることが期待されます。そのため、1 マスの幅と高さを表す Width プロパティと Height プロパティを用意します。

■ImageManager クラス Width プロパティ

public int Width

■ImageManager クラス Height プロパティ

public int Height

実際のテクスチャの幅と高さを変更する必要はありません。これらの値は Draw() メソッドでテクスチャを描画するときの参考値として用います。

個々のテクスチャの取得は、ImageManager クラスのインデクサで作成します。テクスチャは、名前やインデックスで識別することも可能ですが、この場では列挙体を用いて識別することにしました。

■ImageManager クラスのインデクサ

public Texture2D this[ImageName name]

個のインデクサの name パラメータには、テクスチャを識別する ImageName 列挙体の値を指定します。たとえば、ImageName.OneField を指定すると周囲に地雷が 1 つ埋まっているマスのテクスチャが返されるという仕組みです。

Page 23: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

■ImageName 列挙体

public enum ImageName{ NoneField = 0, //隣接するマスに地雷がない空マス OneField = 1, //1 TwoField = 2, //2 ThreeField = 3, //3 FourField = 4, //4 FiveField = 5, //5 SixField = 6, //6 SevenField = 7, //7 EightField = 8, //8 MineField = 16 //地雷のマス}

以上の、MineField クラス、ImageManager クラス、ImageName 列挙体が正しく実行されていれば、次のようなDraw() メソッドでマインスイーパの基本となる地雷原のマス目を描画することができます。

private MineField mineField;private ImageManager images;

protected override void Draw(GameTime gameTime){ graphics.GraphicsDevice.Clear(Color.White); int x = 0, y = 0;

SpriteBatch spriteBatch = new SpriteBatch(graphics.GraphicsDevice); spriteBatch.Begin(); for (int r = 0; r < mineField.Rows; r++) { for (int c = 0; c < mineField.Columns; c++) { Rectangle rect = new Rectangle(x, y, images.Width, images.Height);

if (mineField[c, r]) { spriteBatch.Draw(images[ImageName.MineField], rect, Color.White); } else { int mines = mineField.GetAdjacentMines(c, r); ImageName imageName = (ImageName)Enum.Parse(typeof(ImageName), mines.ToString(), true); spriteBatch.Draw(images[imageName], rect, Color.White); } x += images.Width; } x = 0; y += images.Height; } spriteBatch.End();

base.Draw(gameTime);}

■ WindowsMinesweeper 実行結果

mineField には MineField オブジェクトが、images には ImageManager オブジェクトが、それぞれ適切に初期化された状態で格納されているものとします。個々のマス目は、for 文による繰り返し処理の中で、1 マスごとに描画されています。描画するべきマス目は、対象のマスに地雷があるかどうかを調べて判断しています。地雷がある場合はImageName.MineField に対応するテクスチャを描画します。そうでなければ GetAdjacentMines() メソッドから周囲の地雷の数を取得し、値に対応する ImageName 列挙体の値に変換して ImageManager から取得しています。

このとき、ImageName 列挙体で、隣接するマスの地雷の数に対応するテクスチャを表すメンバの値は、描画する整数に対応しているものとします。たとえば、隣接するマスに地雷が 1 つあるマスは、OneField メンバのテクスチャで描画する必要があります。OneField メンバの値が 1 であれば、GetAdjacentMines() メソッドから取得した数から、Enum 構造体の Parse() メソッドで変換できます。

プロジェクトを実行していただければ分かりますが、これだけではゲームとしては機能しません。起動した時点で、すべてのマス目の結果が表示されている状態です。これをゲームにするには、MineField クラスの各マス目が開かれてい

Page 24: Visual Studio 2008 Express Editions - XNA Game Studio 入門 ...download.microsoft.com/download/4/9/1/4915E136-7EE3-4D8A...開発に自信のない方は、最初は Windows PC 上で

るかどうかを表す情報と、現在、どのマス目が選択されているかを表す情報を追加する必要があります。加えて、コントローラからの入力を受け、ゲームとして反応するプログラムを書かなければなりません。これらの機能は、次回に詳細を解説させていただきます。

Top of Page

プロファイル (個人情報) の管理 | MSDN Flash ニュースレター | ご意見・ご要望

© 2012 Microsoft Corporation. All rights reserved. お問い合せ先 | 使用条件 | 商標 | プライバシー | 日本での個人情報の取り扱い