基于C#彈幕類射擊游戲的實(shí)現(xiàn)——(六)爆炸效果

接下來(lái)就像填充積木一樣慷彤,把GameScene里用到的東西一個(gè)個(gè)寫完~~
先來(lái)個(gè)最簡(jiǎn)單的娄蔼。GameBomb
一目了然

public class GameBomb : GameObject  
    {  
        public bool IsLive;  
          
        private int FrameIndex;  
        private int FrameMax;  
        private float FrameDelay;  
          
        private int FrameWidth;  
        private int FrameHeight;  
        private int FrameHalfWidth;  
        private int FrameHalfHeight;  
          
        private float time;  
          
        public GameBomb(Vector2 position, bool isBig, float duration)  
        {  
            this.Position = position;  
              
            this.FrameIndex = 0;  
            this.FrameMax = Config.BombSmallFrameMax;  
              
            this.FrameWidth = Config.BombSmallFrameWidth;  
            this.FrameHeight = Config.BombSmallFrameHeight;  
            this.FrameHalfWidth = this.FrameWidth / 2;  
            this.FrameHalfHeight = this.FrameHeight / 2;  
              
            this.FrameDelay = duration / (float)this.FrameMax;  
              
            this.IsLive = true;  
        }  
          
        public override void Update(float elapsedTime)  
        {  
            if ( IsLive == false )  
            {  
                return;  
            }  
              
            time += elapsedTime;  
              
            if ( time >= FrameDelay )  
            {  
                time -= FrameDelay;  
                  
                FrameIndex++;  
                  
                if ( FrameIndex >= FrameMax )  
                {  
                    IsLive = false;  
                }  
            }  
        }  
          
        public override void Render(Graphics g)  
        {  
            if ( IsLive == false )  
            {  
                return;  
            }  
              
            g.DrawImage(Data.BombSource,  
                        new Rectangle((int)Position.X - FrameHalfWidth, (int)Position.Y - FrameHalfHeight, FrameWidth, FrameHeight),  
                        new Rectangle(FrameWidth * FrameIndex, 0, FrameWidth, FrameHeight),  
                        GraphicsUnit.Pixel);  
        }  
    }

如果不熟悉的,估計(jì)是對(duì)2D類的精靈動(dòng)畫不太了解底哗。岁诉。可以百度了解下跋选。
或者簡(jiǎn)單講解涕癣,就是按照時(shí)間,不斷的繪制一樣圖片中不同位置的精靈~看起來(lái)就像動(dòng)態(tài)的了前标。
接下來(lái)是它的管理類GameBombManager

public static class GameBombManager  
    {  
        private static List<GameBomb> mBombs = new List<GameBomb>();  
          
        public static void AddBomb(Vector2 position, bool isBig, float duration)  
        {  
            mBombs.Add(new GameBomb(position, isBig, duration));  
        }  
          
        public static void Update(float elapsedTime)  
        {  
            for ( int i = 0; i < mBombs.Count; i++ )  
            {  
                mBombs[i].Update(elapsedTime);  
                  
                if ( mBombs[i].IsLive == false )  
                {  
                    mBombs.RemoveAt(i);  
                    i--;  
                    continue;  
                }  
            }  
        }  
          
        public static void Render(Graphics g)  
        {  
            foreach ( GameBomb bomb in mBombs )  
            {  
                bomb.Render(g);  
            }  
        }  
    } 

這個(gè)看起來(lái)就比我們之前見過的簡(jiǎn)單多了坠韩。
好,這章就這么結(jié)束了:蛏同眯!貌似有點(diǎn)少啊。唯鸭。须蜗。
好吧,那接下來(lái)講一個(gè)與本游戲無(wú)關(guān)的目溉,粒子系統(tǒng)(其實(shí)粒子系統(tǒng)在游戲中很重要明肮,只是這個(gè)游戲很簡(jiǎn)單,沒有用到而已)

public struct GameParticle  
    {  
        /// <summary>  
        /// 粒子位置  
        /// </summary>  
        public Vector2 Position;  
        /// <summary>  
        /// 粒子速度  
        /// </summary>  
        public Vector2 Velocity;  
        /// <summary>  
        /// 重力加速度  
        /// </summary>  
        public float Gravity;  
        /// <summary>  
        /// 直線加速度(運(yùn)動(dòng)方向上的加速度)  
        /// </summary>  
        public float RadialAccel;  
        /// <summary>  
        /// 切線上的加速度(角速度)  
        /// </summary>  
        public float TangentialAccel;  
        /// <summary>  
        /// 粒子旋轉(zhuǎn)角度  
        /// </summary>  
        public float Spin;  
        /// <summary>  
        /// 粒子旋轉(zhuǎn)速度增量  
        /// </summary>  
        public float SpinDelta;  
        /// <summary>  
        /// 粒子大小  
        /// </summary>  
        public float Size;  
        /// <summary>  
        /// 粒子大小增量  
        /// </summary>  
        public float SizeDelta;  
        /// <summary>  
        /// 粒子生存時(shí)間  
        /// </summary>  
        public float Age;  
        /// <summary>  
        /// 粒子死亡時(shí)間  
        /// </summary>  
        public float TerminalAge;  
    }  
      
    /// <summary>  
    /// 粒子配置信息  
    /// </summary>  
    public struct GameParticleSystemInfo  
    {  
        /// <summary>  
        /// 粒子貼圖  
        /// </summary>  
        public Bitmap Texture;  
        /// <summary>  
        /// 每秒發(fā)射的粒子數(shù)量  
        /// </summary>  
        public int Emission;  
        /// <summary>  
        /// 生命周期  
        /// </summary>  
        public float LifeTime;  
        /// <summary>  
        /// 粒子生命周期范圍  
        /// </summary>  
        public Range ParticleLife;  
        /// <summary>  
        /// 方向  
        /// </summary>  
        public float Direction;  
        /// <summary>  
        /// 偏移角度  
        /// </summary>  
        public float Spread;  
        /// <summary>  
        /// 是否為絕對(duì)值(計(jì)算生成粒子的初始速度)  
        /// </summary>  
        public bool IsRelative;  
        /// <summary>  
        /// 速度范圍  
        /// </summary>  
        public Range Speed;  
        /// <summary>  
        /// 重力加速度范圍  
        /// </summary>  
        public Range Gravity;  
        /// <summary>  
        /// 直線加速度范圍  
        /// </summary>  
        public Range RadialAccel;  
        /// <summary>  
        /// 切線角加速度范圍  
        /// </summary>  
        public Range TangentialAccel;  
        /// <summary>  
        /// 起始大小  
        /// </summary>  
        public float SizeStart;  
        /// <summary>  
        /// 最終大小  
        /// </summary>  
        public float SizeEnd;  
        /// <summary>  
        /// 大小變化量  
        /// </summary>  
        public float SizeVar;  
        /// <summary>  
        /// 起始旋轉(zhuǎn)角度  
        /// </summary>  
        public float SpinStart;  
        /// <summary>  
        /// 最終旋轉(zhuǎn)角度  
        /// </summary>  
        public float SpinEnd;  
        /// <summary>  
        /// 角度變化值  
        /// </summary>  
        public float SpinVar;  
    }  
      
    /// <summary>  
    /// 粒子系統(tǒng)  
    /// </summary>  
    public class GameParticleSystem  
    {  
        /// <summary>  
        /// 粒子最大數(shù)量  
        /// </summary>  
        public const int MaxParticles = 512;  
          
        /// <summary>  
        /// 粒子系統(tǒng)未啟動(dòng)  
        /// </summary>  
        public const float Particle_System_Not_Start = -2.0f;  
          
        /// <summary>  
        /// 粒子發(fā)射器的配置信息  
        /// </summary>  
        public GameParticleSystemInfo Info;  
          
        private GameParticle[] mParticles; // 粒子集合  
          
        /// <summary>  
        /// 剩余時(shí)間  
        /// </summary>  
        private float Age;  
          
        /// <summary>  
        /// 剩余未發(fā)射粒子  
        /// </summary>  
        private float EmissionResidue;  
        private Vector2 PrevPosition; // 上一個(gè)位置  
        private Vector2 Position; // 當(dāng)前位置  
        private Vector2 Offset; // 偏移量  
        private float Scale; // 整體縮放系數(shù)  
          
        /// <summary>  
        /// 活動(dòng)粒子個(gè)數(shù)  
        /// </summary>  
        private int ParticlesAlive;  
          
        public GameParticleSystem(GameParticleSystemInfo info)  
        {  
            this.mParticles = new GameParticle[MaxParticles];  
              
            this.Info = info;  
            this.Position = new Vector2(0, 0);  
            this.PrevPosition = new Vector2(0, 0);  
            this.Offset = new Vector2(0, 0);  
            this.Scale = 1.0f;  
              
            this.EmissionResidue = 0;  
            this.ParticlesAlive = 0;  
            this.Age = Particle_System_Not_Start;  
        }  
          
        /// <summary>  
        /// 移動(dòng)粒子發(fā)射器到制動(dòng)位置  
        /// </summary>  
        /// <param name="x">橫坐標(biāo)</param>  
        /// <param name="y">縱坐標(biāo)</param>  
        /// <param name="moveParticles">是否移動(dòng)活動(dòng)粒子</param>  
        public void MoveTo(float x, float y, bool moveParticles)  
        {  
            float dx = 0;  
            float dy = 0;  
              
            if ( moveParticles )  
            {  
                dx = x - Position.X;  
                dy = y - Position.Y;  
                  
                for ( int i = 0; i < ParticlesAlive; i++ )  
                {  
                    mParticles[i].Position.X += dx;  
                    mParticles[i].Position.Y += dy;  
                }  
                  
                PrevPosition.X = PrevPosition.X + dx;  
                PrevPosition.Y = PrevPosition.Y + dy;  
            }  
            else  
            {  
                if ( Age == Particle_System_Not_Start )  
                {  
                    PrevPosition.X = x;  
                    PrevPosition.Y = y;  
                }  
                else  
                {  
                    PrevPosition.X = Position.X;  
                    PrevPosition.Y = Position.Y;  
                }  
            }  
              
            Position.X = x;  
            Position.Y = y;  
        }  
          
        /// <summary>  
        /// 啟動(dòng)粒子系統(tǒng)  
        /// </summary>  
        public void Start()  
        {  
            if ( Info.LifeTime == -1.0f )  
            {  
                Age = -1.0f;  
            }  
            else  
            {  
                Age = 0;  
            }  
        }  
          
        /// <summary>  
        /// 在指定位置啟動(dòng)粒子系統(tǒng)  
        /// </summary>  
        /// <param name="x">橫坐標(biāo)</param>  
        /// <param name="y">縱坐標(biāo)</param>  
        public void Start(float x, float y)  
        {  
            Stop(false);  
            MoveTo(x, y, false);  
            Start();  
        }  
          
        /// <summary>  
        /// 停止粒子系統(tǒng)  
        /// </summary>  
        /// <param name="killParticles">是否摧毀活動(dòng)粒子</param>  
        public void Stop(bool killParticles)  
        {  
            Age = Particle_System_Not_Start;  
              
            if ( killParticles )  
            {  
                ParticlesAlive = 0;  
            }  
        }  
          
        public float GetAge()  
        {  
            return Age;  
        }  
          
        public void Update(float elapsedTime)  
        {  
            float ang = 0;  
            Vector2 accel1;  
            Vector2 accel2;  
              
            if ( Age >= 0 )  
            {  
                Age += elapsedTime;  
                  
                if ( Age >= Info.LifeTime )  
                {  
                    Age = Particle_System_Not_Start;  
                }  
            }  
              
            for ( int i = 0; i < ParticlesAlive; i++ )  
            {  
                mParticles[i].Age += elapsedTime;  
                  
                if ( mParticles[i].Age >= mParticles[i].TerminalAge )  
                {  
                    ParticlesAlive--;  
                    mParticles[i] = mParticles[ParticlesAlive];  
                    i--;  
                    continue;  
                }  
                  
                // 計(jì)算粒子直線加速度  
                accel1 = mParticles[i].Position - Position;  
                accel1.Normalize();  
                accel2 = accel1;  
                accel1 = accel1 * mParticles[i].RadialAccel;  
                  
                // 計(jì)算粒子切線加速度  
                ang = accel2.X;  
                accel2.X = -accel2.Y;  
                accel2.Y = ang;  
                accel2 = accel2 * mParticles[i].TangentialAccel;  
                  
                // 計(jì)算粒子速度  
                mParticles[i].Velocity += (accel1 + accel2) * elapsedTime;  
                mParticles[i].Velocity.Y += mParticles[i].Gravity * elapsedTime;  
                  
                mParticles[i].Position += mParticles[i].Velocity * elapsedTime;  
                  
                mParticles[i].Spin += mParticles[i].SpinDelta;  
                mParticles[i].Size += mParticles[i].SizeDelta;  
            }  
              
            if ( Age != Particle_System_Not_Start )  
            {  
                // 計(jì)算需要生成的粒子數(shù)量  
                float ParticlesNeeded = Info.Emission * elapsedTime + EmissionResidue;  
                int ParticlesCreated = (int)((uint)ParticlesNeeded);  
                  
                EmissionResidue = ParticlesNeeded - ParticlesCreated;  
                  
                int n = ParticlesAlive;  
                for ( int i = n; i < n + ParticlesCreated; i++ )  
                {  
                    if ( ParticlesAlive >= MaxParticles )  
                    {  
                        break;  
                    }  
                      
                    mParticles[i].Age = 0;  
                    mParticles[i].TerminalAge = Info.ParticleLife.Get();  
                      
                    mParticles[i].Position = PrevPosition + (Position - PrevPosition) * Helper.GetRandomFloat(0, 1);  
                    mParticles[i].Position.X += Helper.GetRandomFloat(-2.0f, 2.0f);  
                    mParticles[i].Position.Y += Helper.GetRandomFloat(-2.0f, 2.0f);  
                      
                    ang = Info.Direction - Data.TwoPI + Helper.GetRandomFloat(0, Info.Spread) - Info.Spread / 2.0f;  
                      
                    if ( Info.IsRelative )  
                    {  
                        ang += (PrevPosition - Position).Angle() + Data.TwoPI;  
                    }  
                      
                    mParticles[i].Velocity.X = (float)Math.Cos(ang);  
                    mParticles[i].Velocity.Y = (float)Math.Sin(ang);  
                    mParticles[i].Velocity *= Info.Speed.Get();  
                      
                    mParticles[i].Gravity = Info.Gravity.Get();  
                    mParticles[i].RadialAccel = Info.RadialAccel.Get();  
                    mParticles[i].TangentialAccel = Info.TangentialAccel.Get();  
                      
                    mParticles[i].Size = Helper.GetRandomFloat(Info.SizeStart, Info.SizeStart + (Info.SizeEnd - Info.SizeStart) * Info.SizeVar);  
                    mParticles[i].SizeDelta = (Info.SizeEnd - mParticles[i].Size) / mParticles[i].TerminalAge;  
                      
                    mParticles[i].Spin = Helper.GetRandomFloat(Info.SpinStart, Info.SpinStart + (Info.SpinEnd - Info.SpinStart) * Info.SpinVar);  
                    mParticles[i].SpinDelta = (Info.SpinEnd - mParticles[i].Spin) / mParticles[i].TerminalAge;  
                      
                    ParticlesAlive++;  
                }  
            }  
              
            PrevPosition = Position;  
        }  
          
        public void Render(Graphics g)  
        {  
            for ( int i = 0; i < ParticlesAlive; i++ )  
            {  
                g.DrawImage(Data.BulletSource,  
                            new Rectangle((int)(mParticles[i].Position.X * Scale + Offset.X),  
                                          (int)(mParticles[i].Position.Y * Scale + Offset.Y),  
                                          (int)(16.0f * Scale),  
                                          (int)(16.0f * Scale)),  
                            new Rectangle(0, 0, 16, 16),  
                            GraphicsUnit.Pixel);  
            }  
        }  
    }  
      
    /// <summary>  
    /// 粒子管理器  
    /// </summary>  
    public class GameParticleManager  
    {  
        /// <summary>  
        /// 粒子系統(tǒng)最大個(gè)數(shù)  
        /// </summary>  
        public const int MaxParticleSystem = 10;  
          
        private GameParticleSystem[] mPSList;  
        private int mPSCount;  
          
        private Vector2 mOffset;  
        public Vector2 Offset  
        {  
            get  
            {  
                return mOffset;  
            }  
            set  
            {  
                mOffset = value;  
                  
                for ( int i = 0; i < mPSCount; i++ )  
                {  
                    mPSList[i].MoveTo(mOffset.X, mOffset.Y, false);  
                }  
            }  
        }  
          
        public GameParticleManager()  
        {  
            mPSList = new GameParticleSystem[MaxParticleSystem];  
              
            mOffset = new Vector2(0, 0);  
            mPSCount = 0;  
        }  
          
        public void Spwan(float x, float y, GameParticleSystemInfo info)  
        {  
            if ( mPSCount >= MaxParticleSystem )  
            {  
                return;  
            }  
              
            mPSList[mPSCount] = new GameParticleSystem(info);  
            mPSList[mPSCount].Start(x, y);  
              
            mPSCount++;  
        }  
          
        public bool IsAlive(GameParticleSystem psi)  
        {  
            for ( int i = 0; i < mPSCount; i++ )  
            {  
                if ( mPSList[i] == psi )  
                {  
                    return true;  
                }  
            }  
              
            return false;  
        }  
          
        public void Kill(GameParticleSystem psi)  
        {  
            for ( int i = 0; i < mPSCount; i++ )  
            {  
                if ( mPSList[i] == psi )  
                {  
                    mPSList[i] = mPSList[mPSCount - 1];  
                    mPSCount--;  
                    return;  
                }  
            }  
        }  
          
        public void KillAll()  
        {  
            mPSCount = 0;  
        }  
          
        public void Update(float elapsedTime)  
        {  
            for ( int i = 0; i < mPSCount; i++ )  
            {  
                mPSList[i].Update(elapsedTime);  
                  
                if ( mPSList[i].GetAge() == GameParticleSystem.Particle_System_Not_Start )  
                {  
                    mPSList[i] = mPSList[mPSCount - 1];  
                    mPSCount--;  
                    i--;  
                }  
            }  
        }  
          
        public void Render(Graphics g)  
        {  
            for ( int i = 0; i < mPSCount; i++ )  
            {  
                mPSList[i].Render(g);  
            }  
        }  
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缭付,一起剝皮案震驚了整個(gè)濱河市柿估,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陷猫,老刑警劉巖秫舌,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件的妖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡足陨,警方通過查閱死者的電腦和手機(jī)嫂粟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)墨缘,“玉大人星虹,你說(shuō)我怎么就攤上這事∧魉希” “怎么了宽涌?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蝶棋。 經(jīng)常有香客問我卸亮,道長(zhǎng),這世上最難降的妖魔是什么嚼松? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任嫡良,我火速辦了婚禮,結(jié)果婚禮上献酗,老公的妹妹穿的比我還像新娘寝受。我一直安慰自己,他們只是感情好罕偎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布很澄。 她就那樣靜靜地躺著,像睡著了一般颜及。 火紅的嫁衣襯著肌膚如雪甩苛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天俏站,我揣著相機(jī)與錄音讯蒲,去河邊找鬼。 笑死肄扎,一個(gè)胖子當(dāng)著我的面吹牛墨林,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播犯祠,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼旭等,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了衡载?” 一聲冷哼從身側(cè)響起搔耕,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎痰娱,沒想到半個(gè)月后弃榨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菩收,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年鲸睛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坛梁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡腊凶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拴念,到底是詐尸還是另有隱情钧萍,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布政鼠,位于F島的核電站风瘦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏公般。R本人自食惡果不足惜万搔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望官帘。 院中可真熱鬧瞬雹,春花似錦、人聲如沸刽虹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涌哲。三九已至胖缤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阀圾,已是汗流浹背哪廓。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留初烘,地道東北人涡真。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像账月,于是被迫代替她去往敵國(guó)和親综膀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容