Shot Class で弾丸を連射

弾丸を連射する Shot Object Class を作成します。
配列を使った連射は 弾丸を連射 を参照して下さい。

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

Shot Object Class の説明

  1. 弾丸の発射を管理するには、次のような領域が必要です。
            bool      flag;  //描画フラグ
            Texture2D img;   //画像の指定
            Vector2   pos;   //弾の座標
            Vector2   vect;  //進行方向
        
    これらの領域を個々に配列で定義していたのでは、プログラムが煩雑になります。
    そこで Shot Class として定義すると共に、便利なメソッドも作成します。
  2. Shot Class の領域の定義。
            public bool      flag;  //描画フラグ
            public Texture2D img;   //画像の指定
            public Vector2   pos;   //弾の座標
            public Vector2   vect;  //進行方向
        
  3. Shot Class のコンストラクタでは、領域の初期設定を行います。
            public Shot()
            {   pos  = Vector2.Zero;
                vect = Vector2.Zero;
                flag = false;
            }
        
  4. 進行方向(vect)に従って、弾の座標(pos)を更新するメソッドです。
    ウインドウの外に出たときは flag をクリアします。
    800,600 は XNA の規定値ですが、ウインドウサイズを変更するときは修正が必要です。
            public void Move()
            {   if (flag)
                {
                    pos = pos + vect;
                    if (pos.X < -8 || pos.X > 800 || pos.Y < -8 || pos.Y > 600)
                        flag = false;
                }
            }
        
  5. 画像を描画するメソッドです。
    flag が設定されている Class の img の画像を pos の座標の描画します。
            public void Draw(SpriteBatch spBatch)
            {
                if (flag)
                {
                    spBatch.Draw(img, pos, Color.White);
                }
            }
        

プログラムの説明

  1. 自機と敵機と弾丸の画像を定義しています。
    自機はキーで操作します。
    敵機は左右の往復運動を繰り返します。
    ShotArray が弾丸を連射する Shot Class の配列です。
            //-----テクスチャ変数------------------------------------------
            public Texture2D myship;                    //自機テクスチャ
            public Texture2D enemy;                     //敵テクスチャ
            public Texture2D tama;                      //弾テクスチャ
    
            //-----キャラクタ位置情報--------------------------------------
            public Vector2 mypos;                       //自機の位置
            public Vector2 enemypos;                    //敵の位置
            public Vector2 vct;                         //敵の移動方向
            double settim;                              //弾の設定時間
    
            //-----弾の配列--------------------------------------
            static Shot[]  ShotArray = new Shot[3];     //ショットの配列
            //static Shot[]  ShotArray = new Shot[10];  //ショットの配列
        
  2. ShotArray[] に Shot Class を配列の大きさに合わせて生成します。
    ShotArray.GetLength(0) を使うと配列のサイズが変わっても対応できます。
            protected override void Initialize()
            {       一部省略
                mypos = new Vector2(400-25, 600-50);    //自機の位置の設定
                enemypos = new Vector2(0, 0);           //敵の位置の設定
                vct.X = 2;                              //敵移動方向の初期化
                vct.Y = 0;
                settim = 0;
                //弾の配列を初期化
                for(int i=0; i<ShotArray.GetLength(0); i++)   ShotArray[i] = new Shot();
    
                base.Initialize();
            }
        
  3. LoadContent() メソッドに Texture2D を生成するコードを追加します。
    画像を直接入力すると、透明色が設定されません。
    透明にするには、PNG 形式の画像に透明色を設定して保存して下さい。
    リソースで取り込むと、透明色が設定されていなくても紫色が透明になります。
            protected override void LoadContent()
            {
                // Create a new SpriteBatch, which can be used to draw textures.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // TODO: use this.Content to load your game content here
                //myship = Content.Load<Texture2D>("myship"); //自機テクスチャ読込み
                //enemy = Content.Load<Texture2D>("enemy");   //敵テクスチャ読込み
                //tama = Content.Load<Texture2D>("tama");     //弾テクスチャ読込み
                myship = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\myship.png");
                enemy = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\enemy.png");
                tama = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\tama.png");
            }
        
  4. Update() メソッドです。
    teki_move(), jiki_move() で機体を移動します。
    tama_shoot(gameTime) で Space キーで弾丸を発射します。
    ShotArray[i].Move() で弾丸を移動します。
            protected override void Update(GameTime gameTime)
            {
                // ゲームを終了する
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                    Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit();
    
                // ゲームの処理はここから書く。
                teki_move();
                jiki_move();
                // 弾の発射
                tama_shoot(gameTime);
                // 弾の移動
                for(int i=0; i<ShotArray.GetLength(0); i++)  ShotArray[i].Move();
    
                base.Update(gameTime);
            }
        
  5. Draw() メソッドに画像を描画するコードを追加します。
    spriteBatch.Draw() で自機と敵機を描画します。
    弾丸の描画には ShotArray[i].Draw() メソッドを使っています。
            protected override void Draw(GameTime gameTime)
            {
                graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // TODO: ここに描画処理を記述します。
                spriteBatch.Begin();                                //描画開始
                spriteBatch.Draw(myship, mypos, Color.White);       //自機描画
                spriteBatch.Draw(enemy, enemypos, Color.White);     //敵描画
                //弾を描画
                for (int i=0; i<ShotArray.GetLength(0); i++)
                    ShotArray[i].Draw(spriteBatch);
                spriteBatch.End();
    
                base.Draw(gameTime);
            }
        
  6. 敵機は左右の往復運動を繰り返します。
            public void teki_move ( )
            {
                enemypos += vct;
                if (enemypos.X > 750)   vct.X = -2 ;
                if (enemypos.X < 0)     vct.X = 2 ;
            }
        
  7. 自機は矢印キーで操作します。
    Vector2.Clamp() で自機が移動する範囲を制限しています。
            public void jiki_move ( )
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Left))   mypos.X -= 4;
                if (Keyboard.GetState().IsKeyDown(Keys.Right))  mypos.X += 4;
                if (Keyboard.GetState().IsKeyDown(Keys.Up))     mypos.Y -= 3;
                if (Keyboard.GetState().IsKeyDown(Keys.Down))   mypos.Y += 3;
                mypos = Vector2.Clamp(mypos, new Vector2(0,400), new Vector2(750,550));
            }
        
  8. Space キーで弾丸を連射します。
    前回の発射(settim)から 300 ミリ秒を置いて、次の弾丸を発射します。
    ShotArray[i].flag で空いている領域を調べて弾丸を設定します。
            public void tama_shoot(GameTime gameTime)
            {   int     i;
    
                if (Keyboard.GetState().IsKeyDown(Keys.Space))
                {
                    if (settim + 300 < gameTime.TotalGameTime.TotalMilliseconds)
                    {
                        for(i=0; i<ShotArray.GetLength(0) && ShotArray[i].flag; i++);
                        if (i<ShotArray.GetLength(0))
                        {   settim = gameTime.TotalGameTime.TotalMilliseconds;
                            ShotArray[i].flag = true;
                            ShotArray[i].img = tama;
                            ShotArray[i].pos = mypos;
                            ShotArray[i].vect.Y = -4;
                        }
                    }
                }
            }
        

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

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