TCRに学ぶ
人によっては見たくない三文字
Xbox 360でゲーム開発をしているときに聞く単語のひとつにTCR(Technical Certification Requirements)というものがあります。コンシューマーゲーム機用のゲームを出すためには、このTCRで決められた要求を満たす必要があります。例えば「コントローラーの接続が切れたら、ゲームをポーズ状態にしてユーザーに対してコントローラーの再接続を促すメッセージを表示する」と、いった感じです。プロジェクトの追い込み時期になるとバグデータベースにある直さないといけないバグのリストでよく目にする単語だったりするので、良い思い出がない開発者もいると思います。
全てのTCRを満たすのは面倒な作業ではありますが、その殆どがプレイしてくれるユーザーが快適にゲームをプレイする為には必要不可欠なものばかりです。そこで、今回は数あるTCRの中からXNA GS上でゲームを作るときにも役に立つTCRをいくつか紹介します。
- 同じ画面を5秒以上続けて表示しない
- ユーザーが操作できない状態が15秒以上続く場合は、ユーザーを飽きさせない工夫をする
- メッセージはセーフエリア内に表示
- アンチエリアスを使ってね
「同じ画面を5秒以上続けて表示しない」
通称5秒ルール。例えばタイトル画面を「Push Start」と描きこまれた静止画一枚を表示したりするとアウトです。要するに常に画面のどこかが動いていることで、ユーザーにゲームが固まってしまった状態ではないと認識させるものです。
簡単な解決方法としては、Push Startといった文字は別に表示してカラーアニメーションさせたり、点滅させたりする方法があります。3Dモデルを表示できるのなら、3Dモデルをゆっくりと回転させるといった手もあります。
ゲームが固まった状態と区別できるという実用的な目的のほかに、常に画面上にアニメーションする部分があると、していないものに比べると楽しく見えるという効果もあるので、ゲーム画面のデザインをするときにアニメーションも考慮することをお勧めします。
「ユーザーが操作できない状態が15秒以上続く場合は、ユーザーを飽きさせない工夫をする」
これはロード画面のことで、Xbox 360のゲームでは「Now Loading...」という単に文字を表示させるだけではなく、ゲームの進行に関する情報や、ゲームプレイ時のTIPSなどを表示しているのは、この要求を満たすためです。以前は単に文字列を表示するという単純なものが大半をしめていましたが、最近では次のミッションの説明をしている間に裏でロードしてるというゲームも見られるようになりました。
ユーザを飽きさせないというのはゲームを作る上で非常に大事なことなので、常にユーザーを楽しませるように努力しましょうということを奨励しているTCRです。
「メッセージはセーフエリア内に表示」
PC用のモニタと違って、TVモニタの場合は画面の上下左右が切れてしまうことがあります。ですから、そのことを考慮せずに画面端にゲームにHPゲージやスコアといったものを表示するとTVによっては見えなくなることがあります。
この問題を避けるためにゲーム中に表示されるメッセージなどは、解像度の90%のセーフエリアといわれる領域に表示するようにします。1280x720の場合はスクリーン座標の(64、36)から(1216、684)の152x648の大きさの部分にメッセージを描くようにします。特に重要度の高いメッセージは解像度の80%の部分に表示するように決められています。
と、数字で書いても判らないので、例として1280x720の時のセーフエリアを表示したイメージ(クリックするとオリジナルサイズで表示します)を作ってみました。上の図の明るい部分がセーフエリアになっています。
ただし、同じセーフエリアをPCモニタ上でも適応すると今度は周りに空白が目立つようになるので、その空白が気にならないデザインにするか、セーフエリアの矩形情報を持っておき、Xbox 360上では解像度の90%の大きさにし、PC上では解像度と同じ大きさにするようにして「セーフエリアの右端からxピクセルの位置」といった感じに指定できるようにする方法があります。
「アンチエリアスを使ってね」
Xbox 360のeDRAMは4xMSAA使用時にピーク性能を発揮できるように設計されていて、少ない容量のeDRAMに収まらないサイズでも負荷を抑えながら分割してレンダリングするタイリングをサポートしています。せっかくある機能を使って欲しいのでアンチエリアスを使うことが奨励されています。
PCの場合でもXNAを動かすのに必要なシェーダーモデル1.1が使える殆どのビデオカードにはアンチエリアス機能があり、特に最近のビデオカードでは4xMSAA以上のアンチエリアスを使っても速度的なペナルティが少ないものが多くなってきました。また、XNA GS上ではタイリングを気にせずに大きなサイズのレンダーターゲットを指定できるようになっています。
左上の図は4xMSAAありで、右上がAAなしの時のスクリーンショット(クリックで拡大表示)です。
上の図は等倍の比較図です。静止画でも違いが判ると思いますが、実際に動かしてみるとAAなしの場合はポリゴンのエッジ部分にでるちらつきが4xMSAAでは殆どありません。
実際の使い方ですが、以下のPreparingDeviceSettingイベントにフックするコードをゲームクラスのコンストラクタ部分に追加します。
public Game()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreparingDeviceSettings +=
new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
}
そして、以下のコードを追加するとXbox 360、PCの両方でアンチエリアスが使えるようになります。PCの方はアンチエリアスをサポートしていないビデオカードもあるので、CheckDeviceMultiSampleTypeを使ってアンチエリアスが使用可能かのチェックをしています。
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
PresentationParameters pp = e.GraphicsDeviceInformation.PresentationParameters;
// 4xAAと2xAAが使えるなら使っちゃう
GraphicsAdapter adapter = e.GraphicsDeviceInformation.Adapter;
SurfaceFormat format = adapter.CurrentDisplayMode.Format;
// 使いたいAAのタイプを順に使えるか調べる
MultiSampleType[] multiSampleTypes = {
MultiSampleType.FourSamples,
MultiSampleType.TwoSamples
};
foreach (MultiSampleType mst in multiSampleTypes )
{
int quality = 0;
if (adapter.CheckDeviceMultiSampleType(DeviceType.Hardware, format,
false, mst, out quality))
{
// 最初に見つけた使用可能なAAを設定する。
pp.MultiSampleQuality = 0;
pp.MultiSampleType = mst;
break;
}
}
}
アンチエリアスがビデオカードで使用できるようになった頃はアンチエリアスを使ったときの速度低下が大きな問題でしたが、前述のように今時のGPU上でのアンチエリアス使用時の負荷は少なく、Xbox 360上では4xMSAA使用時の負荷は使用していないときに比べると20%程の増加になります。特にGPUがヒマになりがちなXNAフレームワーク上で動いてるゲームでは常に使用していても速度的な変化は殆どないので、最初に4xMSAAを使うようにして、GPUの負荷が多くなったときに2xMSAA、AAなしと変えるようにしてみてはどうでしょうか?