カスタムクラス側

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace DelegateTestXNA
{
    //サービス利用の為のインターフェイス
    interface IElementListProvider
    {
        IList<Element> ElementList { get; }
    }

    //サービスに登録するインスタンスメンバーを含んだクラス。インターフェイスを継承し外部に公開を指定する
    class ElementListProvider :IElementListProvider
    {
        List<Element> elementList;

        public IList<Element> ElementList
        {
            get { return elementList; }
        }

        public ElementListProvider()
        {
            elementList = new List<Element>();
        }
    }

    //プレーヤーキャラクタや敵キャラクタの要素(エレメント)の基底となるクラス
    class Element
    {
        public delegate void eventUpdateDelegate(GameTime gameTime);

        //メンバー
        //ゲームのエレメントの基底に必要そうなメンバーをここで加える
        public bool IsFinish;
        public float value;
        protected eventUpdateDelegate UpdateDelegate;

        IElementListProvider elementListProvider;

        public Element(Game game)
        {
            IsFinish = false;    //エレメントが生まれた際にfalseになっている
            value = 0;
            elementListProvider = (IElementListProvider)game.Services.GetService(typeof(IElementListProvider));
        }

        public virtual void Update(GameTime gameTime)
        {
            UpdateDelegate(gameTime);
        }
    }

    class BulletEmitter : Element
    {
        float power;

        public BulletEmitter(Game game, int request)
            : base(game)
        {
            power = 1;

            switch (request)
            {
                case 0:
                    UpdateDelegate = TypeA_update;
                    break;
                case 1:
                    UpdateDelegate = TypeB_update;
                    break;
                case 2:
                    UpdateDelegate = TypeC_update;
                    break;
            }
        }

        public void TypeA_update(GameTime gameTime)
        {
            value = value + 0.01f * power;
            IsFinish = true;
        }

        public void TypeB_update(GameTime gameTime)
        {
            value = value + 0.1f * power;
        }

        public void TypeC_update(GameTime gameTime)
        {
            value = value + 1f * power;
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }
    }
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
フレームワーク側

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace DelegateTestXNA
{
    /// <summary>
    /// 基底 Game クラスから派生した、ゲームのメイン クラスです。
    /// </summary>

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        ElementListProvider elementListProvider;    //フレームワークの何処からでもサービスを利用してアクセスできるコレクションのプロパイダークラス

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //インスタンスをXNAフレームワークのサービスに登録
            elementListProvider = new ElementListProvider();
            Services.AddService(typeof(IElementListProvider), elementListProvider);
        }

        /// <summary>
        /// ゲームの開始前に実行する必要がある初期化を実行できるようにします。
        /// ここで、要求されたサービスを問い合わせて、非グラフィック関連のコンテンツを読み込むことができます。
        /// base.Initialize を呼び出すと、任意のコンポーネントが列挙され、
        /// 初期化もされます。
        /// </summary>
        protected override void Initialize()
        {
            // TODO: ここに初期化ロジックを追加します。
            base.Initialize();
        }

        /// <summary>
        /// LoadContent はゲームごとに 1 回呼び出され、ここですべてのコンテンツを
        /// 読み込みます。
        /// </summary>

        
        protected override void LoadContent()
        {
            // 新規の SpriteBatch を作成します。これはテクスチャーの描画に使用できます。
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: this.Content クラスを使用して、ゲームのコンテンツを読み込みます。
        }

        /// <summary>
        /// UnloadContent はゲームごとに 1 回呼び出され、ここですべてのコンテンツを
        /// アンロードします。
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: ここで ContentManager 以外のすべてのコンテンツをアンロードします。
        }

        /// <summary>
        /// ワールドの更新、衝突判定、入力値の取得、オーディオの再生などの
        /// ゲーム ロジックを、実行します。
        /// </summary>
        /// <param name="gameTime">ゲームの瞬間的なタイミング情報</param>
        ///
        bool firstLoop =true;

        protected override void Update(GameTime gameTime)
        {
            // ゲームの終了条件をチェックします。
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: ここにゲームのアップデート ロジックを追加します。

            //最初の一度目のみ実行
            //Update内からでもリストを更新出来る事を理解してください
            if (firstLoop)
            {
                elementListProvider.ElementList.Add(new BulletEmitter(this, 0));
                elementListProvider.ElementList.Add(new BulletEmitter(this, 1));
                elementListProvider.ElementList.Add(new BulletEmitter(this, 2));
                firstLoop = false;
            }

            //リストのコレクション内updateメソッドを実行しIsActiveがfalseになるとコレクションから消去する
            //foreachのステートメントでは不可能な操作なのでよく参考にする事
            for (int i = 0; i < elementListProvider.ElementList.Count;)
            {
                Element item=elementListProvider.ElementList[i];
                item.Update(gameTime);
                if (item.IsFinish)      //ここでIsFinishを確認してtrueならコレクションから取り除く
                {
                    elementListProvider.ElementList.Remove(item);
                }
                else
                {
                    i++;
                }
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// ゲームが自身を描画するためのメソッドです。
        /// </summary>
        /// <param name="gameTime">ゲームの瞬間的なタイミング情報</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: ここに描画コードを追加します。

            base.Draw(gameTime);
        }
    }
}
最終更新:2012年07月29日 21:29