前に書いたGameComponentのメモの続きです。
今回は、Game1登録したらUpdate()だけでなくDraw()メソッドも自動で呼ばれるGameComponentの作り方を乗せます。
XNAには描画も出来るGameComponentが既に備わっています。GameComponentクラスの代わりに、DrawableGameComponentクラスを継承するとLoadContent()メソッドとDraw()メソッドをオーバーライドできます。Initialize()とUpdate()同様Game1内のbase.メソッド名()で順番に呼ばれます。
今回は前に作ったFPSカウンターのクラスで実装例を書きます。まず、FPSカウンターのクラスで、DrawableGameComponentクラスを継承し、コンストラクタも書きます。
class FPSCounter : DrawableGameComponent { float m_fps; // 実際のFPS float m_interval; // FPSの更新速度(殆どの場合は1秒) float m_updateTimer; // 更新するまでを計るタイマー int m_frameCount; // 現在のフレーム数 SpriteBatch m_spriteBatch; SpriteFont m_font; public FPSCounter(Game game) : base(game) { m_fps = 0.0f; m_interval = 1.0f; m_updateTimer = 0.0f; m_frameCount = 0; }
次に、LoadContent()メソッドをオーバーライドします。
protected override void LoadContent() { m_spriteBatch = new SpriteBatch(Game.GraphicsDevice); m_font = Game.Content.Load<SpriteFont>("Font"); base.LoadContent(); }
そして、Draw()メソッドをオーバーライドします。
public override void Draw(GameTime gameTime) { // フレーム数を増やす(目標は1秒に60回) m_frameCount++; // タイマーに前のフレームから過ぎた時間を加算する m_updateTimer += (float)gameTime.ElapsedGameTime.TotalSeconds; // タイマーが1秒を超えたら if (m_updateTimer > m_interval) { // FPSを計算する, 速度が下がっていた場合はここで差を計算する m_fps = m_frameCount / m_updateTimer; // タイマーとカウンターをリセットする m_frameCount = 0; m_updateTimer -= m_interval; } // FPSの数値を描画する m_spriteBatch.Begin(); m_spriteBatch.DrawString(m_font, string.Format("FPS: {0:F2}", m_fps), new Vector2(0, 0), Color.Black); m_spriteBatch.DrawString(m_font, string.Format("FPS: {0:F2}", m_fps), new Vector2(1, 1), Color.White); m_spriteBatch.End(); base.Draw(gameTime); } } // クラス実装終了
今回は紹介していませんが、GameComponent同様Initialize()とUpdate()メソッドもオーバーライド出来ます。
最後に、Game1クラス内で、FPSカウンターを登録します。
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; // Inputクラスをコンポーネントとして、登録する Components.Add(new Input(this)); // FPSクラスを描画できるコンポーネントとして、登録する Components.Add(new FPSCounter(this)); }
これで、Game1でDraw()メソッドを呼ばなくても、自動的にFPSが描画されます(SpriteFontは事前にプロジェクトに追加しましたので、そのままコピペしても動きません)。
今回は以上です。