ガベージコレクションを起動

ガベージコレクション(Garbage Collection)のプログラムです。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの説明

  1. Object Class の呼び出しを繰り返すと、ゲームが一時中断することがあります。
    これはヒープ領域が足らなくなって、ガベージコレクションが起動されるためです。
    メモリ領域は、コード領域, 静的データ領域, スタック領域, ヒープ領域などに分けて管理されます。
    ヒープ領域は Object Class が起動されたときや、new でメモリ領域を確保したときに割り当てられます。
    C# や XNA では使い終わった領域は、ガベージコレクションが働いて再利用が出来るようになります。
    ガベージコレクションが起動されるのは、一般的に使い終わった領域が溜まって、メモリが不足したときです。
    このプログラムでは、開放された領域のサイズを常時タイトルバーに表示します。
    long wk = GC.GetTotalMemory(false);
    また Enter Key で強制的にガベージコレクションを起動します。
    GC.Collect();
  2. 弾丸を発射するために、基本的な Object Class を作成しました。
    Arrayを使うので System.Collections; を定義して下さい。
    StringBuilder を使うので System.Text; を定義して下さい。
        using System.Collections;
        using System.Text;
        
  3. w はヒープ領域の消費量を増やすために定義した余分な領域です。
        public class Shot
        {
            public Texture2D    img;        //画像の指定
            public Vector2      pos;        //弾の座標
            public Vector2      vect;       //進行方向
            public string       w;          //余分な領域
    
            //コンストラクタ
            public Shot(Texture2D Img, Vector2 Pos, Vector2 Vect)
            {   img = Img;
                pos  = Pos;
                vect = Vect;
                w = new String('A', 1000);
            }
            public void Draw(SpriteBatch spBatch)
            {
                spBatch.Draw(img, pos, Color.White);
            }
    
            //弾の移動
            public bool Move()
            {
                pos = pos + vect;
                if (pos.X < -8 || pos.X > 800 || pos.Y < -8 || pos.Y > 600) return true;
                return false;
            }
        }
        
  4. 弾丸を連射するための領域を定義します。
            public      Texture2D tama;         //弾テクスチャ
            ArrayList   ShotArray;              //ショットの ArrayList
            Vector2     Rotvect;                //回転座標の領域
            double      Settim;                 //前回発射時刻
            double      Speed = 150;            //発射の間隔
        
  5. Update() メソッドです。
    開放された領域のサイズを常時タイトルバーに表示します。
    Speed の時間間隔で同心円状に弾丸を発射します。
    tama_shoot(gameTime); が発射するメソッドです。
    上下キーで発射間隔(Speed)を調整します。
    Enter キーで強制的にガベージコレクションを起動します。
            protected override void Update(GameTime gameTime)
            {
                // ゲームを終了する
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
                    ButtonState.Pressed  ||
                    Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit();
    
                // ヒープ領域の表示
                StringBuilder sb = new StringBuilder();
                sb.Append("GetTotalMemory=");
                long wk = GC.GetTotalMemory(false);
                sb.AppendFormat("{0,8}", wk.ToString());
                string wstr = sb.ToString();
                base.Window.Title = wstr;
    
                // 弾の移動
                for(int i=0; i<ShotArray.Count; i++)
                {
                    bool flag = ((Shot)ShotArray[i]).Move();
                    if (flag)   ShotArray.RemoveAt(i);
                }
    
                // 弾の発射
                if (Settim + Speed < gameTime.TotalGameTime.TotalMilliseconds)
                {
                    Settim = gameTime.TotalGameTime.TotalMilliseconds;
                    tama_shoot(gameTime);
                }
    
                // 上下キーで発射間隔を調整
                if (Keyboard.GetState().IsKeyDown(Keys.Up))
                {   if (Speed > 10)   Speed -= 1; }
                if (Keyboard.GetState().IsKeyDown(Keys.Down)) Speed += 1;
    
                // Enter でガベージコレクション
                if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                {   GC.Collect();  }
    
                base.Update(gameTime);
            }
        
  6. 同心円状に弾丸を発射する tama_shoot() メソッドです。
            public void tama_shoot(GameTime gameTime)
            {
                for (int i=0; i<36; i++)
                {
                    Rot(i*10, 0, 4);
                    ShotArray.Add(new Shot(tama, new Vector2(400,300), Rotvect));
                }
            }
        
  7. 回転座標を計算する Rot メソッドです。
            public void Rot(float rt, float px, float py)
            {
                Rotvect.X = (float)(px * Math.Cos(rt / 180 * 3.14) - py * Math.Sin(rt / 180 * 3.14));
                Rotvect.Y = (float)(px * Math.Sin(rt / 180 * 3.14) + py * Math.Cos(rt / 180 * 3.14));
            }
        
  8. Shot Object Class や弾丸を発射するプログラムの説明は、他のページを参照して下さい。

【NOTE】

このプログラムではガベージコレクションの実行時間は全く気になりませんでした。 (?_?;
小さなメモリを消費する多数の Object Class が起動されて、ヒープ領域を使い切ったときに中断するのでしょうか?。
強制的にガベージコレクションを起動するのは、多少プログラムが中断しても気にならないときに実行して下さい。
またはガベージコレクションに時間がかかりすぎる前に、こまめに実行するのも手でしょうか? (^_^;)

前田稔(Maeda Minoru)の超初心者のプログラム入門

超初心者のプログラム入門(XNA(C#) game program)