ゲーム用フレームワーク、その2

■クラスを使ってシーンを整理しよう
前回の「ゲーム用フレームワーク、その1」は、簡単なプログラムではよいのですが、大きなプログラムになっていくと複雑になってしまいバグの元になります、それと分業とかがしにくくなるので、クラスを切り替えて使用する方法をとります。

■ソース

Game1.cs :メインの部分
Screen.cs :シーンのベースクラス
Screen01.cs :表示したいシーン01
Screen02.cs :表示したいシーン02

Game1.cs

namespace WindowsGame
{
    public enum GAME_MODE
    {
        screen01,
        screen02
    }
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        ContentManager content;
        private static Screen currentScreen;
        private int gameMode = (int)GAME_MODE.screen01;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            content = new ContentManager(Services);
        }

        protected override void Initialize()
        {
            currentScreen = new Screen01(this);
            base.Initialize();
        }

        protected override void Update(GameTime gameTime)
        {
            int oldMode = gameMode;

            gameMode = currentScreen.Update(gameTime);
            if (gameMode != oldMode)
            {
                currentScreen.Shutdown();
                switch (gameMode)
                {
                    case (int)GAME_MODE.screen01:
                        currentScreen = new Screen01(this);
                        break;
                    case (int)GAME_MODE.screen02:
                        currentScreen = new Screen02(this);
                        break;
                }
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            currentScreen.Render();
            base.Draw(gameTime);
        }

        public GraphicsDeviceManager GetGraphicsDeviceManager()
        {
            return graphics;
        }
    }
}

Screen.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace WindowsGame
{
    class Screen
    {
        protected Game1 game = null;

        public Screen(Game1 game)
        {
            this.game = game;
        }

        public virtual int Update(GameTime time)
        {
            return -1;
        }

        public virtual void Render()
        {
        }

        public virtual void Shutdown()
        {
        }
    }
}

Screen01.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame
{
    class Screen01 : Screen
    {
        int count;

        public Screen01(Game1 game) : base(game)
        {
            count = 0;
        }

        public override int Update(GameTime time)
        {
            if (++count == 120)
                return (int)GAME_MODE.screen02;
            return (int)GAME_MODE.screen01;
        }

        public override void Render()
        {
            GraphicsDeviceManager graphics = game.GetGraphicsDeviceManager();
            graphics.GraphicsDevice.Clear(Color.Black);
        }
    }
}

Screen02.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame
{
    class Screen02 : Screen
    {
        int count;

        public Screen02(Game1 game) : base(game)
        {
            count = 0;
        }

        public override int Update(GameTime time)
        {
            if (++count == 120)
                return (int)GAME_MODE.screen01;
            return (int)GAME_MODE.screen02;
        }

        public override void Render()
        {
            GraphicsDeviceManager graphics = game.GetGraphicsDeviceManager();
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
        }
    }
}

■ソース説明
今回「currentScreen」をインターフェースとして「Screen01」「Screen02」を設定しなおして
「currentScreen」の「Update」「Render」「Shutdown」を実行すると、設定されている「Screen01」「Screen02」クラスの「Update」「Render」「Shutdown」が呼ばれます。
「Screen01」「Screen02」クラスは「Screen」クラスを継承しているので、このような動作になります。
「Screen」クラスには「Update」「Render」「Shutdown」が「virtual」で宣言してあり「Screen01」「Screen02」クラスではそれを「override」して関数を上書きするような形になります。ただ「Shutdown」は定義されていないので「Screen」クラスで定義した部分が使用されます。