フォントを使わずに、テキストアドベンチャーをを作るお馬鹿な方法を思いついたので、カッとなって試した。後悔はしていない。

 ロゴ(Windows 版)
神崎隼BLOG-ロゴ

 タイトル(Windows 版)
神崎隼BLOG-ひげねこのなく頃に

 欠点は、Xbox360 上でのキャプチャ画面が撮れない事だが、些細な事であろう。

 ロゴ?(Xbox360 版)
神崎隼BLOG-ロゴ?

AD

ローカライズの注意点

テーマ:
 日本語以外の言語をサポートする時、注意する必要がいくつかあります。

 特に、LocalizationSample のように、アセンブリ リソース ファイルで文字列を扱う時です。
 恐らく、ローカライズは英語のみのゲームが多いと思いますが、リソースは以下のように作成しましょう。

・「リソース名.resx」に英語の文字列を登録し、日本語は「リソース名.ja.resx」に登録する。

 LocalizationSampleと同じ方法で、登録しましょうと言う事です。

 この形式で登録すると、以下のようにリソースが使用されます。

・日本語のXbox360上 → 日本語
・英語のXbox360上 → 英語
・それ以外の言語のXbox360上 → 英語

 これを逆に登録してしまうと、例えば英語はわかるけど日本語はわからないフランス人が、そのゲームを起動すると日本語が出てきてしまい、Xbox360の設定を変えない限り、英語では遊べなくなります。
 むしろ、英語に対応してないと勘違いしてしまう可能性が高いと思います。

 リソースを使わない場合でも、テクスチャ等を言語で分けている場合、日本語環境なら日本用のテクスチャ、それ以外は英語のテクスチャを読み込むと言う形にしておきましょう。

 ところで、日本語大好きフランス人が、日本製のゲームは日本語で遊びたいと思った時は、どうすれば良いでしょうか?
 Xbox360 の設定を日本語にすれば動きますが、切り替えが面倒です。

 ゲーム中で切り替え機能を入れれば、多少は楽になりそうです。

 リソースを使わない場合、特に問題はありませんね。言語情報を変数で確保し、そこを書き換えて、テクスチャ等の再読み込みをするだけで、終了です。

 では、リソースを使う場合は?

 リソース名で作られたクラスには、Cultureと言うプロパティがあるので、そこを書き換えればOKです。

 LocalizationSampleでは、初期化時に以下のように現在のCultureInfoを渡しています。

  Strings.Culture = CultureInfo.CurrentCulture;

 例えば、以下のような感じで、Cultureプロパティを初期化します。

・英語(アメリカ)

  リソース名.Culture = new CultureInfo(0x0409);

・英語(イギリス)

  リソース名.Culture = new CultureInfo(0x0809);

・英語(英語圏全体)

  リソース名.Culture = new CultureInfo(0x0009);

・日本語

  リソース名.Culture = new CultureInfo(0x0011);

 CultureInfoのコンストラクタの引数に渡す値は、CultureInfoのヘルプの表のカルチャ識別子を参照して下さい。

 尚、テクスチャ読み込み時に言語情報を見る場合は、LocalizationSampleのソースとは変えて、リソースのCultureプロパティを参照するようにすると、設定場所が一箇所になるのでうっかりミスも防げると思います。

 そんな感じで、本来遊んで貰えたかも知れない人々に遊んで貰えなくならないようにするためのTIPでした。

AD

スターじゃないラスター

テーマ:
神崎隼BLOG-ラスタースクロール

 今更、Xbox LIVE インディーズ ゲーム開始記念に、ラスタースクロールについて書いてみようのコーナー。

 ラスタースクロールが何かは、説明しなくてもわかると思うけど、画面がグニャグニャするアレ。
 まぁ、知らない人は、ググッて下さい。

 ラスタースクロールにも色々と種類があるようですが、今回は、所謂、横ラスターです。

 XNA でその効果を実装するには、レンダーターゲットにグニャグニャさせたい物を描画して、グニャグニャと描画すれば終わりです。(頭の悪過ぎる説明)

 説明するより、コードを見たり、実行してみたりするのが、早いと思うので、早速、実装方法をサクッと説明。
※アメブロでは半角スペース使えないため、インデントには全角スペースを使用しています。

 とりあえず、Platformer スターター キットに追加する形でするので、それで新規作成して下さい。

 で、まずは、描画用の変数を定義させます。場所はどこでも良いので、PlatformerGame のコンストラクタの手前にでも、以下の定義を放り込んで下さい。

  RenderTarget2D renderTarget;

  int roll = 12;
  int loopCount = 360;
  int count;

 renderTarget はグニャグニャさせる物を描く用で、roll はグニャグニャ度合いみたいに理解して下さい。
 loopCount は count の最大値で、count はカウンターです。loopCount を小さくすると、高速でグニャグニャします。

 さて、続いては変数の初期化。

 LoadContent 関数の中の最後に、次のコードを追加して下さい。

  renderTarget = new RenderTarget2D(GraphicsDevice, BackBufferWidth, BackBufferHeight, 1, SurfaceFormat.Color);

  count = 0;

 今回は、Platformer の通常の描画をラスタースクロールさせるので、バックバッファと同じサイズのレンダーターゲットを作成してます。
 実際に使用する場合は、用途に合わせて変更して下さい。

 初期化が終わって、次は更新処理。

 Update 関数の最後に、次のコードを追加して下さい。

  if (loopCount - 1 > count)
    count++;
  else
    count = 0;

 そして、最後は描画。

 勿論、コードを追加するのは、Draw 関数です。

 追加箇所は二箇所で面倒なので、コードを全て書いてしまいましょう。

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

    GraphicsDevice.SetRenderTarget(0, renderTarget);
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();

    level.Draw(gameTime, spriteBatch);

    spriteBatch.End();

    GraphicsDevice.SetRenderTarget(0, null);

    spriteBatch.Begin();

    Texture2D tex = renderTarget.GetTexture();
    Vector2 vec = new Vector2();
    Rectangle rect = new Rectangle(0, 0, tex.Width, 1);

    for (vec.Y = 0; vec.Y < tex.Height; vec.Y += rect.Height)
    {
      vec.X = (float)((graphics.PreferredBackBufferWidth - tex.Width) / 2 + Math.Cos((count * 360 / loopCount + vec.Y) * MathHelper.Pi / 180) * roll);

      spriteBatch.Draw(tex, vec, rect, Color.White);

      rect.Y += rect.Height;
    }

    DrawHud();

    spriteBatch.End();

    base.Draw(gameTime);
  }

 肝は、for 文の中の一行目の計算ですかね? cos 関数でグニャグニャ位置を計算しています。

 それと、1ドットずつのラスターにしてますが、処理不可が気になる場合は、以下の行の最後の引数を増やして下さい。

  Rectangle rect = new Rectangle(0, 0, tex.Width, 1);

 この1を4にすると、for 文のぶん回し回数が1/4になります。勿論、4ドット単位でのスクロールになりますので、あまり大きくすると良くわからない効果になりますので、注意が必要です。

 どうでも良いですが、DrawHud 関数の呼び出しを level.Draw の後に移動させると、スコアとかもグニャグニャして少し楽しいです。

 さて、「ピクセルシェーダーでできそうな気もするけどやった事ないし、Zune でも動くと思うから」と言う事で、レンダーターゲットを使用した実装方法を紹介してみました。

 蛇足ですが、描画部分をちょっと変更すると縦ラスターにもなります。

AD