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

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

/// <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);
大概就是这样

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,510评论 18 139
  • 这是今天的成果吧,虽然还是没有全部完成,但是大致的功能已经实现,飞机的移动,限制移动范围,子弹的发射,消灭敌人,敌...
    Unity学习的路上阅读 2,815评论 1 2
  • 有了子弹,子弹想有个飞机能发射子弹了。好,现在我们就实现玩家的战机 这是玩家类的定义,当然也是继承自GameObj...
    UnSkyToo阅读 491评论 0 1
  • 昨天,4.2班的老师,来到我们教室为我们讲一节作文课,老师在讲作文的时候也给我们带来了一个游戏,叫“击鼓传花...
    王杨晨阅读 303评论 0 1
  • 华为Mate 9试机照 华为Mate 9试机照 Mate 9试机照 华为Mate 9试机照 华为Mate 9试机照...
    灵津渡阅读 217评论 0 1