基于C#弹幕类射击游戏的实现——(三)子弹的实现

2017-09-19  本文已影响0人  UnSkyToo

到这里,我们似乎该让主角上场了,好就让我们来显示一颗子弹吧~
慢着,显示子弹之前,我们需要小小的抽象一下,把游戏中所有能显示的物体抽象。

/// <summary>  
    /// Description of GameObject.  
    /// </summary>  
    public class GameObject  
    {  
        public Vector2 Position;  
        public Box BoxCollider;  
          
        protected int Width;  
        protected int Height;  
        protected int HalfWidth;  
        protected int HalfHeight;  
          
        public GameObject()  
        {  
        }  
          
        public virtual void Update(float elapsedTime)  
        {  
              
        }  
          
        public virtual void Render(Graphics g)  
        {  
              
        }  
    }

封装了一些基础属性和方法~~特别说明下:HalfWidth和HalfHeight只是用于计算的时候少一个除法,可以不需要的,后面的代码会看到
对了,特别说明下:一般的坐标系是以左上角为(0,0)点,向右为X正方向,向下为Y正方向。
而这个游戏是以屏幕的中间为远点,绘制图片的时候也是,以图片的中间为绘制点。。。至于为什么这样。。我当时脑抽了,忘了为什么了
接下来就是主角

/// <summary>  
    /// Description of GameBullet.  
    /// </summary>  
    public class GameBullet : GameObject  
    {  
        public bool IsOwn; // 是否为自己的子弹  
        public int Type; // 子弹样式  
        public int Color; // 子弹颜色(0-6)  
        public float ActiveDelay; // 延迟多久激活  
          
        public Vector2 Speed;  
        public Vector2 Accel;  
          
        public bool IsLive; // 是否存活  
          
        public GameBullet(bool isOwn, Vector2 position, Vector2 speed, Vector2 accel, int type, int color, float activeDelay)  
        {  
            this.IsOwn = isOwn;  
            this.Type = type;  
            this.Color = color;  
            this.ActiveDelay = activeDelay;  
              
            this.Position = position;  
            this.Speed = speed;  
            this.Accel = accel;  
              
            this.IsLive = true;  
              
            this.Width = Data.BulletsSize[type].Width;  
            this.Height = Data.BulletsSize[type].Height;  
            this.HalfWidth = this.Width / 2;  
            this.HalfHeight = this.Height / 2;  
              
            this.BoxCollider = new Box((int)position.X, (int)position.Y, this.Width, this.Height);  
        }  
          
        public override void Update(float elaspedTime)  
        {  
            if ( IsLive == false )  
            {  
                return;  
            }  
  
            if (ActiveDelay > 0)  
            {  
                ActiveDelay -= elaspedTime;  
                return;  
            }  
              
            Speed += (Accel * elaspedTime);  
            Position += (Speed * elaspedTime);  
              
            BoxCollider.X = (int)Position.X;  
            BoxCollider.Y = (int)Position.Y;  
              
            if ( Position.X < 0 || Position.Y < 0 || Position.X > Config.ScreenWidth || Position.Y > Config.ScreenHeight )  
            {  
                IsLive = false;  
            }  
        }  
          
        public override void Render(Graphics g)  
        {  
            if ( IsLive == false || ActiveDelay > 0)  
            {  
                return;  
            }  
              
            g.DrawImage(Data.BulletsSource[this.Type],  
                        new Rectangle((int)Position.X - HalfWidth, (int)Position.Y - HalfHeight, Width, Height),  
                        new Rectangle(this.Color * Width, 0, Width, Height),  
                        GraphicsUnit.Pixel);  
              
            if ( Config.IsDebug && Config.IsShowBox )  
            {  
                g.DrawRectangle(Pens.Green, BoxCollider.ToRectangle());  
            }  
        }  
    }

唯一要说明的是Update方法的这两句

    Speed += (Accel * elaspedTime);  
    Position += (Speed * elaspedTime);  

通过速度和加速度来更新子弹的位置,并且在后面同步更新碰撞盒的位置
这里用简单的物理知识来模拟了一下粒子的运行~其实可以做的更复杂一点,比如线速度角速度。
我们这里学习用,就简单一点。东方系列就比较复杂了
子弹肯定不止一个,而且有自己的和敌人的
所以需要一个管理类,用于管理一堆子弹

public class GameBulletManager  
    {  
        private GameScene mScene;  
        private List<GameBullet> mBullets;  
          
        public GameBulletManager(GameScene scene)  
        {  
            this.mScene = scene;  
            this.mBullets = new List<GameBullet>();  
        }  
          
        public void AddBullet(GameBullet bullet)  
        {  
            mBullets.Add(bullet);  
        }  
          
        public void Update(float elapsedTime)  
        {  
            // 检测子弹的碰撞  
            for (int i = 0; i < mBullets.Count; i++)  
            {  
                mBullets[i].Update(elapsedTime);  
  
                if (mBullets[i].IsLive == false)  
                {  
                    mBullets.RemoveAt(i);  
                    i--;  
                    continue;  
                }  
                  
                if ( mBullets[i].IsOwn == false ) // 不是自己的子弹  
                {  
                    if ( mScene.Player1.Collide(mBullets[i].BoxCollider, 1) == true )  
                    {  
                        GameBombManager.AddBomb(mBullets[i].Position, false, 0.5f);  
                        mBullets.RemoveAt(i);  
                        i--;  
                        continue;  
                    }  
                }  
                else  
                {  
                    if ( mScene.EnemyManager.Collide(mBullets[i].BoxCollider, 1) == true )  
                    {  
                        GameBombManager.AddBomb(mBullets[i].Position, false, 0.5f);  
                        mBullets.RemoveAt(i);  
                        i--;  
                        continue;  
                    }  
                    if ( mScene.BossManager.Collide(mBullets[i].BoxCollider, 1) == true )  
                    {  
                        GameBombManager.AddBomb(mBullets[i].Position, false, 0.5f);  
                        mBullets.RemoveAt(i);  
                        i--;  
                        continue;  
                    }  
                }  
            }  
        }  
          
        public void Render(Graphics g)  
        {  
            foreach (GameBullet bullet in mBullets)  
            {  
                bullet.Render(g);  
            }  
              
            if ( Config.IsDebug )  
            {  
                g.DrawString("Bullets:" + mBullets.Count.ToString(), Data.NormalFont, Brushes.Red, 300, 0);  
            }  
        }  
    } 

这里面没有遇到的类暂且不管。
大体上就是用一个List来保存所有GameBullet~~更新和绘制也是一个循环
唯一要做的就是检测子弹和其余单位是否碰撞了,碰撞的话要添加爆炸效果,然后移除这个子弹
好,现在你可以添加几个子弹来玩玩了。
比如,创建一个直线上升的子弹
AddBullet(new Bullet(false, new Vector2(0, 0), new Vector2(0, -300), Vector2.Zero, 0, 0, 0);
创建一个斜着飞的子弹
AddBullet(new Bullet(false, new Vector2(0, 0), new Vector2(300, -300), Vector2.Zero, 0, 0, 0);
创建一个越飞越快的子弹
AddBullet(new Bullet(false, new Vector2(0, 0), new Vector2(0, -300), new Vector2(0, -100), 0, 0, 0);
大概就是这样

上一篇 下一篇

猜你喜欢

热点阅读