您的位置:首页 > 编程语言 > C#

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

2013-12-17 18:44 549 查看
我写博客喜欢做完一个东西,一口气写很多章。。。貌似这样不太好啊~

到这里,我们似乎该让主角上场了,好就让我们来显示一颗子弹吧~

慢着,显示子弹之前,我们需要小小的抽象一下,把游戏中所有能显示的物体抽象成GameObject,好处是什么?好处是看起来很帅。。

当然不是,好处简单来说,整合公共部分、利于管理~~好吧我也不知道好处。。。。

/// <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);


大概就是这样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: