Dust を大量に噴射する

シンプルな Base Class を継承して Dust を大量に撒き散らします。

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

プログラムの説明

  1. シンプルな Base Class を継承して、UFO のアニメーションと大量の Dust を描画するプログラムを作成します。
    10機の UFO が大量の Dust を撒き散らしながら飛び回ります。
    UFO のアニメーションと画像の回転と大量の画像の描画がテーマです。
  2. 極力シンプルに作成した Base Class です。
    説明は他のページを参照して下さい。
        public class Base
        {
            public Vector2 pos;        //弾の座標
            public Vector2 vect;       //進行方向
    
            //コンストラクタ
            public Base(Vector2 Pos, Vector2 Vect)
            {
                pos = Pos;
                vect = Vect;
            }
            public Base()
            {
                pos = Vector2.Zero;
                vect = Vector2.Zero;
            }
    
            //画像の描画
            public void Draw(SpriteBatch spBatch, Texture2D Img)
            {
                spBatch.Draw(Img, pos, Color.White);
            }
            public void Draw(SpriteBatch spBatch, Texture2D Img, Vector2 Pos)
            {
                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;
            }
            public bool Move(Rectangle rect)
            {
                pos = pos + vect;
                if (pos.X < rect.Left || pos.X > rect.Right || pos.Y < rect.Top || pos.Y > rect.Bottom)
                    return true;
                return false;
            }
        }
        
  3. Base Class を継承した画像を回転して描画する Rot Class です。
    軽くするために img は Class 全体で一個の領域しか割り当てません。
    turn は画像の回転係数です。
        public class Rot : Base
        {
            public static Texture2D img;  //画像の指定
            float turn;
    
            //コンストラクタ
            //基本クラスのコンストラクタを呼ぶ場合は base を使う。
            public Rot(Texture2D Img) : base()
            {
                img = Img;
            }
            public Rot(Texture2D Img, Vector2 Pos, Vector2 Vect)
                : base(Pos, Vect)
            {
                img = Img;
            }
        
  4. 画像の回転を設定するコンストラクタの説明です。
    Pos が UFO(噴射する機体)の座標で、x, y が Dust の流れる方向です。
    bturn は { -10, 10, -5, 5, 0 } で UFO から同時に5個の Dust を発射するので、適当に散りばめます。
    Dust の画像は方向性を持っているので、目標の方向に回転します。
    画像の回転の説明は Enemy の方向に Ship を向ける を参照して下さい。
            //Pos:発射座標, x,y:目標座標
            public Rot(Texture2D Img, Vector2 Pos, float x, float y, float bturn) : base()
            {
                float dx, dy;
                float c, s;
                float rad;
    
                img = Img;
                c = (float)(Math.Cos(MathHelper.ToRadians(bturn)));
                s =(float)( Math.Sin(MathHelper.ToRadians(bturn) ));
                dx = x - Pos.X;
                dy = y - Pos.Y;
                rad = (float)Math.Atan2((double)dy, (double)dx);
                dx = (float)(Math.Cos(rad) * 10);
                dy = (float)(Math.Sin(rad) * 10);
                vect.X = c * dx - s * dy;
                vect.Y = s * dx + c * dy;
                pos.X = Pos.X + 20;
                pos.Y = Pos.Y + 20;
                rad = rad + MathHelper.ToRadians(90);
                turn = rad ;
            }
        
  5. Rot Class の続きで画像の描画です。
    通常の描画と、画像を回転しながら描画するメソッド DrawRot() を定義しています。
            //画像の描画
            public void Draw(SpriteBatch spBatch)
            {
                Draw(spBatch, img);
            }
            public void Draw(SpriteBatch spBatch, Vector2 Pos)
            {
                Draw(spBatch, img, Pos);
            }
            public void DrawRot(SpriteBatch spBatch)
            {
                spBatch.Draw(img, pos, null, Color.White, turn, new Vector2(8, 8), 1.0f, SpriteEffects.None, 1.0f);
            }
        }
        
  6. Base Class を継承した Anime Class です。
    軽くするために img は Class 全体で一個の領域しか割り当てません。
    tim はアニメーションのタイミングを計る領域です。
    アニメーションしながら描画する DrawAnime() メソッドを定義しています。
    その他の説明は他のページを参照して下さい。
        public class Anime : Base
        {
            public static   Texture2D img;  //画像の指定
            public int      xn,yn;          //横と縦の枚数
            public int      xs,ys;          //横と縦のサイズ
            public int      sp_no;          //Image No
            private double  tim;            //アニメタイム
    
            //コンストラクタ
            //基本クラスのコンストラクタを呼ぶ場合は base を使う。
            public Anime(Texture2D Img) : base()
            {
                img = Img;
                sp_no = 0;
                xn = 1;
                yn = 1;
                xs = Img.Width;
                ys = Img.Height;
            }
            public Anime(Texture2D Img, Vector2 Pos, Vector2 Vect) : base(Pos, Vect)
            {
                img = Img;
                sp_no = 0;
                xn = 1;
                yn = 1;
                xs = Img.Width;
                ys = Img.Height;
            }
            public Anime(Texture2D Img, int Xn, int Yn) : base()
            {
                img = Img;
                sp_no = 0;
                xn = Xn;
                yn = Yn;
                xs = Img.Width / xn;
                ys = Img.Height / yn;
            }
            public Anime(Texture2D Img, Vector2 Pos, Vector2 Vect, int Xn, int Yn, int Sp_no)
                : base(Pos, Vect)
            {
                img = Img;
                sp_no = Sp_no;
                xn = Xn;
                yn = Yn;
                xs = Img.Width / xn;
                ys = Img.Height / yn;
            }
    
            //画像の描画
            public void Draw(SpriteBatch spBatch)
            {
                Draw(spBatch, img);
            }
            public void Draw(SpriteBatch spBatch, Vector2 Pos)
            {
                Draw(spBatch, img, Pos);
            }
            public void Draw(SpriteBatch spBatch, Vector2 Pos, int No)
            {   int xw,yw;
    
                if (No < xn*yn)
                {   xw= No%xn;
                    yw= No/xn;
                    spBatch.Draw(img, Pos, new Rectangle(xw*xs,yw*ys,xs,ys),Color.White);
                }
            }
            public void DrawAnime(SpriteBatch spBatch, GameTime gameTime, double Tim)
            {   int xw,yw;
    
                xw= sp_no%xn;
                yw= sp_no/xn;
                spBatch.Draw(img, pos, new Rectangle(xw*xs,yw*ys,xs,ys),Color.White);
                Loop(gameTime, Tim);
            }
    
            //次の画像番号
            public void Loop(GameTime gameTime, double Tim)
            {
                double nowtim = gameTime.TotalGameTime.TotalMilliseconds;
                if (sp_no < xn * yn && tim + Tim < nowtim)
                {   tim = nowtim;
                    sp_no = (sp_no + 1) % (xn * yn);
                }
            }
            public bool Next(GameTime gameTime, double Tim)
            {
                if (sp_no < xn * yn)
                {   double nowtim = gameTime.TotalGameTime.TotalMilliseconds;
                    if (tim + Tim < nowtim)
                    {   tim = nowtim;
                        sp_no++;
                    }
                }
                if (sp_no >= xn * yn)
                {   sp_no = 99;
                    return true;
                }
                return false;
            }
        }
        
  7. ufo と dust はテクスチャ画像です。
    UFO と DUST は ArrayList です。
    settim は Dust を噴射するタイミングを計る領域です。
    posw と vectw はヒープ領域を節約するために使用します。
    bturn は同時に5個の Dust を発射するので、適当に散りばめるための配列です。
            public Texture2D ufo;               //UFOテクスチャ
            public Texture2D dust;              //ダストテクスチャ
    
            ArrayList   UFO;                    //UFO の ArrayList
            ArrayList   DUST;                   //ダストの ArrayList
    
            double      settim = 0;             //設定時間
            Vector2     posw = Vector2.Zero;
            Vector2     vectw = Vector2.Zero;
            Random      rand = new Random();
            float[]     ways ={ -10, 10, -5, 5, 0 };
        
  8. LoadContent() メソッドでテクスチャをロードします。
    10機の UFO を ArrayList に登録します。
    UFO のテクスチャは、5枚のアニメーション用の画像が横に並んでいます。
                // TODO: use this.Content to load your game content here
                ufo = Content.Load("enemy_pata");
                dust = Content.Load("enemy_tama");
    
                //自機の設定
                for (int i = 0; i < 10; i++)
                {
                    UFO.Add(new Anime(ufo, new Vector2(rand.Next(700), rand.Next(500)), 
                                           new Vector2(rand.Next(300)/100+3.0f, rand.Next(200)/100+2.0f), 5, 1, i % 5));
                }
        
  9. Update() メソッドで UFO を移動するメソッドを呼び出します。
    Dust は Rot Class の Move() で移動して、ウインドウの外に出ると ArrayList から削除します。
    settim + 50 毎に10機の UFO から5個の Dust(合計50個)を噴射します。
    Dust の進む方向は UFU の座標により、四隅に向きを変えています。
                // UFO の移動
                ufo_move();
                // Dust の移動
                for(i=0; i<DUST.Count; i++)
                {
                    if (((Rot)DUST[i]).Move())   DUST.RemoveAt(i);
                }
                // Dust の発射
                if (settim + 50 < gameTime.TotalGameTime.TotalMilliseconds)
                {   settim = gameTime.TotalGameTime.TotalMilliseconds;
                    for (int j = 0; j < UFO.Count; j++)
                    {   
                        vectw.X = 0;
                        if (((Anime)UFO[j]).vect.X < 0) vectw.X = 780;
                        vectw.Y = 0;
                        if (((Anime)UFO[j]).vect.Y < 0) vectw.Y = 580;
                        for (i = 0; i < 5; i++)
                        {
                            DUST.Add(new Rot(dust, ((Anime)UFO[j]).pos, vectw.X, vectw.Y, ways[i]));
                        }
                    }
                }
        
  10. Draw() メソッドに画像を描画するコードを追加します。
    UFO は DrawAnime() でアニメーションしながら描画します。
    Dust は DrawRot() で画像を回転して描画します。
                spriteBatch.Begin();
                //アニメーションしながらUFOを描画
                foreach(Anime anime in UFO) anime.DrawAnime(spriteBatch,gameTime,100);
                //Dust を描画
                foreach(Rot rot in DUST)    rot.DrawRot(spriteBatch);
                spriteBatch.End();
        
  11. UFO を移動する ufo_move() メソッドです。
    10機の UFO はウインドウの枠に当たると跳ね返ります。
    跳ね返りの処理は、枠に当たると vect の符号を反転するだけです。
            public void ufo_move()
            {
                for(int i=0; i<UFO.Count; i++)
                {
                    ((Anime)UFO[i]).pos += ((Anime)UFO[i]).vect;
                    if (((Anime)UFO[i]).pos.X < -10 || ((Anime)UFO[i]).pos.X > 750)
                        ((Anime)UFO[i]).vect.X = 0 - ((Anime)UFO[i]).vect.X;
                    if (((Anime)UFO[i]).pos.Y < 0 || ((Anime)UFO[i]).pos.Y > 550)
                        ((Anime)UFO[i]).vect.Y = 0 - ((Anime)UFO[i]).vect.Y;
                }
            }
        

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

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