はじめに
SDLというライブラリをご存知でしょうか。SDLはオープンソースで開発されている、シンプルな構成のマルチメディアプログラミング向けライブラリです。SDLは、その手軽さから多くのプログラミング言語向けに様々な実装が存在しています。その中から本稿では、2回に分けて「SDL.NET」という.NET Framework向け実装の一つを紹介しようと思います。
後編となる今回は、SDL.NETの持つ機能のうち、画面に直接文字を書く機能、そしてキーボードの入力に関連したInputライブラリおよび、BGMや効果音の再生に関連したAudioライブラリについて、その機能を解説したいと思います。
対象読者
本稿では、開発環境としてVisual Studio 2008 Professional Editionを、開発言語としてC#言語を利用します。また、利用するSDL.NETのバージョンは6.1.0とします。対象読者としては、C#言語で何らかのプログラムを作ったことがあって、なおかつ手軽なゲームプログラミングに興味があり、Visual StudioやC#言語についてある程度の知識がある方を想定しています。SDLや他のゲームライブラリでのゲーム作成経験があるとなお理解しやすいと思います。前・後編の後編にあたりますので、前編を先に参照ください。
画面に表示するオブジェクト
前編に引き続き、PONというゲームを題材に、そのプログラムの各部分を見ていこうと思います。
前編でゲームマネジメントクラスまでは解説しましたので、後編では見える部品を扱うクラスについての解説から始めたいと思います。 見える部品とは、ゲーム中に登場するパドルやボールなど、画面に描かれるオブジェクトのことです。 PONでは、それらに共通した機能をGameBaseというクラスに抽象化して、そこから派生する形で各種の見える部品を表現しています。
//-- 見える部品の画像をスプライトとして保持する protected Sprite _g; //== 画像の読み込み処理 //== 引数:読み込む画像ファイル名 public virtual void LoadImage(string filename) { _g = new Sprite(filename); _w = _g.Width; _h = _g.Height; _g.Transparent = true; _g.TransparentColor = Color.Lime; }
見える部品の画像は、すべてSpriteクラスのオブジェクトとして保持しています(リスト1)。今回のような単純なプログラムでは、Spriteクラスを用いて画像を確保することと、Surfaceクラスを用いて画像を保持することとに大きな違いはありませんので、Surfaceクラスを用いても構いません。しかし、Spriteクラスでは画像を回したり、アニメーションさせたりといった、ゲームでよく使う操作がカプセル化されていますので、今後の拡張を考え、Spriteクラスで保持するようにしました。
ここで用意したSpriteクラスのオブジェクトに画像を読み込むのが、LoadImageメソッドです。 画像の読み込みはとても簡単で、Spriteクラスのコンストラクタに画像ファイルのパスを渡すだけです。 さらに画像の透過についても、SpriteのTransparentプロパティをTrueに設定して、透過したい色を選ぶだけという手軽さです。 加えてSDL.NETではPNG形式の画像を扱うことができるので、そちらで透過情報を記録して、それを利用することもできます。
今回のサンプルではファイルパスの区切り文字を指定するために、Windows環境でおなじみの円記号(\)ではなく、Path.Directoryという特殊な文字を使っています。これはマルチプラットフォームを見越した処理で、こうしておくことでLinuxなど、Windowsとは異なるパス区切り文字を利用している環境下でも、パス区切り文字について.NET Frameworkが処理してくれるため、何もしなくても、プログラムを動作させることができます。
画面への描画
見える部品が用意できても、プレイヤーの目に見えなければゲームとして意味がありません。そこで次に、画面へ見える部品を描画する処理を見ていきます。先ほどの解説の通り、描画はシーンオブジェクトが担っているので、ゲームの中核を成すシーンオブジェクトである、SceneGameクラスで行われている描画処理を見ながら解説していきます。
//== 画面の描画処理 //== 引数:画面への参照 public override void Draw(SdlDotNet.Graphics.Surface s) { base.Draw(s); //-- ボールを移動させる parent.ball.Move(parent); //-- パドル、壁、ボール、スコアの順で、ビジュアル部品を描画 s.Blit(parent.player.graphic, new Point(parent.player.x, parent.player.y)); s.Blit(parent.wall.graphic, new Point(parent.wall.x, parent.wall.y)); s.Blit(parent.ball.graphic, new Point(parent.ball.x, parent.ball.y)); s.Blit(parent.score.graphic, new Point(parent.score.x, parent.score.y)); }
画面への描画は実に簡単で、Videoオブジェクトへの参照として確保したscreenオブジェクトを通じてBlitメソッドを呼び出し、その引数に描画したいSpriteオブジェクトと、画面上での描画位置を指定してやるだけです。 Blitメソッドで描画されたものは、即座にVideoオブジェクトに反映されますが、即座に画面で見えるわけではありません。というのもSurfaceオブジェクト自体がダブルバッファリングを行っており、Blitメソッドで描かれるのは通常バックバッファにある画面だからです。従って、Tickイベントなどで必ず画面のUpdateを行い、バックバッファとフロントバッファを切り替え、Blitしたオブジェクトが確実に画面上に表示されるようにしてやる必要があるのです。