今更、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 でも動くと思うから」と言う事で、レンダーターゲットを使用した実装方法を紹介してみました。
蛇足ですが、描画部分をちょっと変更すると縦ラスターにもなります。