XNA で文字表示

まずはコチラをご参照あれ。

ひにけにXNA - Content Pipeline その3 そのカスタマイズ:
 http://blogs.msdn.com/ito/archive/2007/05/02/content-pipeline-part3.aspx

 
エラく大変な思いをして文字表示をしているが、その背景として
XNA で日本語が表示できない」
という現状がある。
 
XNAで文字を取り扱う(表示する)場合、スプライトフォントを使用する。
が、単純に MessageBox.Show("てすと") のようなことは出来ない。
ある程度のコーディングを経て文字表示が出来ても、英数字しか取り扱えない。
 
それを解決したサンプルが冒頭で紹介した記事だ。
初心者ながらに「これは素晴らしい!」と思い、早速試してみることにした。
 
私の環境は以下(スペックは別記事参照)
 Visual Studio 2005 Standard Edition
 XNA Game Studio 2.0
 
さて、まず一つ目の躓き。
記事で作成した sln / csproj 他ソース等一式はダウンロードできる。
開いてみたところ、
 

        • -

プロジェクトファイル '*** 略 *** TextMessageSample\Pipeline\Pipeline.csproj' を開けません。
プロジェクトの種類がこのインストールでサポートされていません。

        • -

プロジェクトファイル '*** 略 *** TextMessageSample\Sample\SampleWin.csproj' を開けません。
プロジェクトの種類がこのインストールでサポートされていません。

        • -

プロジェクトファイル '*** 略 *** TextMessageSample\Runtime\RuntimeWin.csproj' を開けません。
プロジェクトの種類がこのインストールでサポートされていません。

        • -

 
だそうな。
記事には「GSE 1.0 Refreshが必要」と記載があった。
GSE 1.0 Refresh と GS 2.0 のバージョン違いの問題かと思い、csproj ファイルの該当部分と思しき文字列(1.0/1.0.0.0)を直してみたが、結果は変わらなかった。
仕方ないので、ソースを参考に自作してみる。
ソリューションとプロジェクトを自作してみる。
ダウンロードしたソリューションは TextMessageSample だったので、TextMessageSample2 でソリューションを新規作成するところから始める。
 
エラーメッセージからもわかる通り、ソリューションにプロジェクトは3つ。
初期プロジェクト作成はSampleプロジェクトと判断し、Windows Game プロジェクトで新規作成。
(アイコンファイルとかがあったので。。。
 
Game1.cs を SampleGame.cs に変更。
Pipeline と Runtime は、Sampleプロジェクトと同列のディレクトリとソースだけコピって準備しておいた。
で、Visual Studio のメニューから「ファイル」→「新規作成」→「既存のコードからプロジェクトを作成」。
Visual C# を指定し、共にクラスライブラリとしてプロジェクトを作成。
sln/suo ファイルなどは削除、Sampleプロジェクトのソリューションに Pipeline/Runtime プロジェクトを追加。
で、とりあえず枠は出来たのかな。
 
ここからどうやってコンパイル・ビルドを通すか、が次なる課題。
パッと見の問題は、
・Sampleプロジェクトの SampleGame.cs が元々のTextMessageSampleプロジェクトの SampleGame.cs を踏襲していないこと
・Pipeline/Runtime プロジェクトが Visual C# Class Library(非XNA)プロジェクトとして作成されていること。
 
とか思って、まずは Pipeline のビルドを通すのに参照設定とか色々…
 
TextImporter.cs

using Microsoft.Xna.Framework.Content.Pipeline;

 
そんな矢先、こんな using を発見して、オブジェクトブラウザから XNA Framework の中身を覗いてみる。
 
Microsoft.Xna.Framework.Content
+ContentLoadException
+ContentManager
+ContentReader
+ContentSerializerAttribute
+ContentSerializerCollectionItemNameAttribute
+ContentSerializerIgnoreAttribute
+ContentTypeReader
+ContentTypeReader
+ContentTypeReaderManager
+ResourceContentMananger
 
…ないじゃん。
Pipeline なくなってる!!
 
別のクラスに代替なのかもしれない。
とか思って諦めかけたら違った。
参照設定で追加しなくちゃいけなかった。
 
Pipeline プロジェクトに Microsoft.Xna.Framework 関連の参照と、System / System.Xml 参照を追加。
すると、以下のビルドエラーになった。
 

        • -

'〜略〜\TextMessageSample2\Runtime\obj\Debug\Runtime.exe' は、エントリ ポイントに適切な静的 'Main' メソッドを含んでいません
'〜略〜\TextMessageSample2\Runtime\bin\Debug\Runtime.exe' メタデータが見つかりませんでした。

        • -

 
これはまだ Runtime のビルド通ってないから当然。
概ね良好なのではないかと思う。
よって、Runtime プロジェクトのビルドにチャレンジ。
 

        • -

'〜略〜\TextMessageSample2\Runtime\obj\Debug\Runtime.exe' は、エントリ ポイントに適切な静的 'Main' メソッドを含んでいません

        • -

 
Main がないということで、Sampleプロジェクト側の調整がまだだ。
そっちが先か。
SampleGame.cs をとりあえず、TextMessageSample のコードに合わせてみた。
 

        • -

'〜略〜\TextMessageSample2\Runtime\obj\Debug\Runtime.exe' は、エントリ ポイントに適切な静的 'Main' メソッドを含んでいません
'〜略〜\TextMessageSample2\Runtime\bin\Debug\Runtime.exe' メタデータが見つかりませんでした。

        • -

 
んー、よくよく見れば、というか、気づいてはいたが、Runtime.exe に Main がないって言ってる。
元々クラスライブラリを指定して作ったが、XNA のクラスライブラリではない。
というか、exe を探しに行くはずじゃないんだけど。
XNA 初心者とか言う前に、Visual Studio に関する知識不足がここで祟った気がする。
 
いやいや、もうちょっと食い下がろう。
exeを参照しようとしていること自体おかしい。
ということで、Runtime プロジェクトをクラスライブラリで作り直したらすんなりビルドが通ってしまった。
なんてこった。。。
(記事を書きながらチャレンジしているわけだが、ここで時間を浪費したことは言うまでもない…
 
Pipeline / Runtime プロジェクトのビルドは通った。
2つのdllが正しく参照できる状態になった、ということだ。
そして、Sample プロジェクトのリビルド。
 

        • -

メンバ 'Sample.SampleGame.LoadGraphicsContent(bool)' は 古い形式の メンバ 'Microsoft.Xna.Framework.Game.LoadGraphicsContent(bool)' をオーバーライドします。Obsolete 属性を 'Sample.SampleGame.LoadGraphicsContent(bool)' に追加してください。 D:\01.data\01_40.for_application\vsproject\cs\XNAGS2.0\TextMessageSample2\Sample\SampleGame.cs
メンバ 'Sample.SampleGame.UnloadGraphicsContent(bool)' は 古い形式の メンバ 'Microsoft.Xna.Framework.Game.UnloadGraphicsContent(bool)' をオーバーライドします。Obsolete 属性を 'Sample.SampleGame.UnloadGraphicsContent(bool)' に追加してください。 D:\01.data\01_40.for_application\vsproject\cs\XNAGS2.0\TextMessageSample2\Sample\SampleGame.cs

        • -

 
上記二つの警告が出た。
 

@IT - C#入門 - 第20回 実行時に参照可能な属性:
 http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_020/csharp_abc04.html

 
まあ、Obsolete とはいえ、現段階では問題なく動くはず。
上記警告メソッドにそれぞれ Obsolete 属性を付加することで、警告は消えた。

// LoadGraphicsContent用Obsolete
[Obsolete("Called when graphics resources need to be loaded. Override this method to load any game-specific graphics resources.")]
// UnloadGraphicsContent用Obsolete
[Obsolete("Called when graphics resources need to be unloaded. Override this method to unload any game-specifc graphics resources.")]

 
さて実行してみる。
 

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
      GraphicsDevice gd = graphics.GraphicsDevice;

      if (loadAllContent)
      {
        spriteBatch = new SpriteBatch(gd);
        textMessage = content.Load<TextMessage>("SampleMessage");
      }

    }

 
content.Load("SampleMessage");
 
で例外が発生する。
 

Microsoft.Xna.Framework.Content.ContentLoadException はハンドルされませんでした。
Message="Error loading \"SampleMessage\". File not found."
Source="Microsoft.Xna.Framework"
StackTrace:
場所 Microsoft.Xna.Framework.Content.ContentManager.OpenStream(String assetName)
場所 Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T](String assetName, Action`1 recordDisposableObject)
場所 Microsoft.Xna.Framework.Content.ContentManager.Load[T](String assetName)
場所 Sample.SampleGame.LoadGraphicsContent(Boolean loadAllContent) 場所 〜略〜\TextMessageSample2\Sample\SampleGame.cs:行 81
場所 Microsoft.Xna.Framework.Game.Initialize()
場所 Sample.SampleGame.Initialize() 場所 〜略〜\TextMessageSample2\Sample\SampleGame.cs:行 64
場所 Microsoft.Xna.Framework.Game.Run()
場所 Sample.Program.Main(String[] args) 場所 〜略〜\TextMessageSample2\Sample\Program.cs:行 14

 
つまり、SampleMessage が存在しない、と。
更に詳細に見てみると、xnbファイルが見つけられない、とのこと。
 
元記事に立ち帰ってみる。
(ここではSample)プロジェクトのプロパティで、Content Pipelineタブ画面で"Add"ボタンを押し、作ったパイプライン用のアセンブリを追加…。
って、プロジェクトのプロパティにそんなタブ画面がないっ!
 
記事自体もそうだけど、Blog全体を(つまり他の記事も含め)見てみると、まだまだわからないことだらけ。
xnbを作る流れ自体、今回XNA GSE 1.0 Refresh からXNA GS 2.0 に移植したコード自体の理解、などが絶対的に足りない。
せっかくデバッグ出来るところまで到達したので、まだ色々やってみたいが、今日はココマデ。
 
 
 
P.S.
 ホントに挑戦しながら書いた記事なので、読み返すとわかりづらい。。。
 もしコレを読む方がいたらゴメンナサイ。