基于C#弹幕类射击游戏的实现——(七)弹幕类实现
如果只有這些子彈,那看起來必然是很一般的,想想看,只有幾顆子彈,孤零零的從下面跑到上面。。。。。
GameBarrage彈幕類,用于創(chuàng)建一些酷炫叼的彈幕~~其實核心也就是通過一些數(shù)學(xué)公式,然后批量AddBullet而已~~
先來看看類型的定義
public enum BarrageType{Line,RotateAndShoot,CrossLine,Circle}
初步就這四種,其余的彈幕類型都可以通過這幾種組合出來
然后就是彈幕的具體實現(xiàn)
?
public class GameBarrage{private GameScene mScene;public GameBarrage(GameScene scene){this.mScene = scene;}/// <summary>/// 圓形彈幕/// </summary>/// <param name="isOwn">是否為玩家子彈</param>/// <param name="type">子彈類型</param>/// <param name="color">子彈顏色</param>/// <param name="position">中心點位置</param>/// <param name="speed">子彈移動速度</param>/// <param name="accel">子彈移動加速度</param>/// <param name="interval">每顆子彈的角度間隔</param>/// <param name="delay">延遲發(fā)射時間</param>public void CreateCircle(bool isOwn, int type, int color, Vector2 position, float speed, float accel, int interval, float delay){int angle = 0;while (angle < 360){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(angle, speed), Helper.GetSpeedWithAngle(angle, accel), type, color, delay));angle += interval;}}/// <summary>/// 扇形彈幕/// </summary>/// <param name="isOwn">是否為玩家子彈</param>/// <param name="type">子彈類型</param>/// <param name="color">子彈顏色</param>/// <param name="position">中心點的位置</param>/// <param name="startAngle">扇形的起始角度(向右為0°)</param>/// <param name="endAngle">扇形的結(jié)束角度(順時針)</param>/// <param name="speed">子彈移動速度</param>/// <param name="accel">子彈移動加速度</param>/// <param name="interval">每顆子彈的角度間隔</param>/// <param name="duration">發(fā)射持續(xù)時間(為0表示瞬間發(fā)射所有)</param>/// <param name="delay">延遲發(fā)射時間</param>public void CreateRotateAndShoot(bool isOwn, int type, int color, Vector2 position, int startAngle, int endAngle, float speed, float accel, int interval, float duration, float delay){int count = startAngle;int angle = Math.Abs(endAngle - startAngle);float wait = duration / (float)angle;if ( endAngle > startAngle ){while (count < endAngle){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(count, speed), Helper.GetSpeedWithAngle(count, accel), type, color, (count - startAngle) * wait + delay ));count += interval;}}else{while (count > endAngle){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(count, speed), Helper.GetSpeedWithAngle(count, accel), type, color, (startAngle - count) * wait + delay ));count += interval;}}}/// <summary>/// 直線交叉彈幕/// </summary>/// <param name="isOwn">是否為玩家子彈</param>/// <param name="type">子彈類型</param>/// <param name="color">子彈顏色</param>/// <param name="spawnCount">子彈數(shù)量</param>/// <param name="beginPos1">開始地點一</param>/// <param name="beginPos2">開始地點二</param>/// <param name="crossPos">交叉點</param>/// <param name="speed">子彈移動速度</param>/// <param name="accel">子彈移動加速度</param>/// <param name="duration">發(fā)射持續(xù)時間(為0表示瞬間發(fā)射所有)</param>/// <param name="delay">延遲發(fā)射時間</param>public void CreateCrossLine(bool isOwn, int type, int color, int spawnCount, Vector2 beginPos1, Vector2 beginPos2, Vector2 crossPos, float speed, float accel, float duration, float delay){int count = 0;float wait = duration / (float)spawnCount;while (count < spawnCount){mScene.AddBullet(new GameBullet(isOwn, beginPos1,Helper.GetSpeedWithPosition(beginPos1, crossPos, speed), Helper.GetSpeedWithPosition(beginPos1, crossPos, accel),type, color,wait * count + delay));mScene.AddBullet(new GameBullet(isOwn, beginPos2,Helper.GetSpeedWithPosition(beginPos2, crossPos, speed), Helper.GetSpeedWithPosition(beginPos2, crossPos, accel),type, color,wait * count + delay));count++;}}/// <summary>/// 直線彈幕/// </summary>/// <param name="isOwn">是否為玩家子彈</param>/// <param name="type">子彈類型</param>/// <param name="color">子彈顏色</param>/// <param name="spawnCount">子彈數(shù)量</param>/// <param name="startPos">開始地點</param>/// <param name="targetPos">目標(biāo)地點(用于確定方向而已)</param>/// <param name="speed">子彈移動速度</param>/// <param name="accel">子彈移動加速度</param>/// <param name="duration">發(fā)射持續(xù)時間</param>/// <param name="delay">延遲發(fā)射時間</param>public void CreateLine(bool isOwn, int type, int color, int spawnCount, Vector2 startPos, Vector2 targetPos, float speed, float accel, float duration, float delay){int count = 0;float wait = duration / (float)spawnCount;while (count < spawnCount){mScene.AddBullet(new GameBullet(isOwn, startPos,Helper.GetSpeedWithPosition(startPos, targetPos, speed), Helper.GetSpeedWithPosition(startPos, targetPos, accel),type, color,wait * count + delay));count++;}}/// <summary>/// 隨機(jī)彈幕/// </summary>/// <param name="isOwn">是否為玩家子彈</param>/// <param name="type">子彈類型</param>/// <param name="color">子彈顏色</param>/// <param name="spawnCount">子彈數(shù)量</param>/// <param name="boundary">子彈范圍</param>/// <param name="speed">子彈速度(包括方向)</param>/// <param name="accel">子彈加速度(包括方向)</param>/// <param name="duration">發(fā)射持續(xù)時間(為0表示瞬間發(fā)射所有)</param>/// <param name="delay">延遲發(fā)射時間</param>public void CreateRandom(bool isOwn, int type, int color, int spawnCount, RangeBox boundary, RangeVector speed, RangeVector accel, float duration, float delay){int count = 0;float wait = duration / (float)spawnCount;while (count < spawnCount){Vector2 sp = speed.Get();Vector2 dir = sp;dir.Normalize();mScene.AddBullet(new GameBullet(isOwn, boundary.Get(), sp, dir * accel.Get(), type, color, count * wait + delay));count++;}}}
就來圓形彈幕來講解吧。
首先大家可以看看前面GameBullet,有個字段是用于延遲顯示的(就是說子彈已經(jīng)添加了,只是必須要等到規(guī)定時間過去才能顯示出來)
解析來看具體的實現(xiàn)
public void CreateCircle(bool isOwn, int type, int color, Vector2 position, float speed, float accel, int interval, float delay){int angle = 0;while (angle < 360){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(angle, speed), Helper.GetSpeedWithAngle(angle, accel), type, color, delay));angle += interval;}}
核心思想就是通過“極坐標(biāo)公式”算出不同角度對應(yīng)的坐標(biāo),然后生成子彈
具體的計算就是Helper.GetSpeedWithAngle,這個忘記的可以看前面章節(jié),有寫~
通過累加angle,循環(huán)360°,然后計算出不同角度的速度方向和延遲就能創(chuàng)建圓形彈幕了
再來一個用的最多的扇形彈幕
public void CreateRotateAndShoot(bool isOwn, int type, int color, Vector2 position, int startAngle, int endAngle, float speed, float accel, int interval, float duration, float delay){int count = startAngle;int angle = Math.Abs(endAngle - startAngle);float wait = duration / (float)angle;if ( endAngle > startAngle ){while (count < endAngle){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(count, speed), Helper.GetSpeedWithAngle(count, accel), type, color, (count - startAngle) * wait + delay ));count += interval;}}else{while (count > endAngle){mScene.AddBullet(new GameBullet(isOwn, position, Helper.GetSpeedWithAngle(count, speed), Helper.GetSpeedWithAngle(count, accel), type, color, (startAngle - count) * wait + delay ));count += interval;}}}
原理和上面類似,只是需要注意的是時間延遲傳遞的是? (startAngle-Count)*wait+delay
其實就是通過計算出需要產(chǎn)生的子彈數(shù)量已經(jīng)總的延遲,然后算出每一個子彈的延遲時間。
這樣的效果就是,瞬間產(chǎn)生了一堆子彈,但是看到的是一個個顯示出來,有一種旋轉(zhuǎn)著發(fā)射子彈的感覺。。。表達(dá)不好。。
有了這個東西,就可以看看 BOSS彈幕的生成了,其實就是用了這些函數(shù)而已
public static class BossBarrage{/// <summary>/// 花瓣型彈幕/// </summary>/// <param name="barrage"></param>/// <param name="position"></param>/// <returns>彈幕持續(xù)8秒</returns>public static int Petal(GameBarrage barrage, Vector2 position){barrage.CreateRotateAndShoot(false, 0, 0, position, 0, 300, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 30, 330, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 60, 360, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 90, 390, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 120, 420, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 150, 450, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 180, 480, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 210, 510, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 240, 540, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 270, 570, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 300, 600, 300, -350, 5, 8, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 330, 630, 300, -350, 5, 8, 0);return 8;}/// <summary>/// 直線型彈幕/// </summary>/// <param name="barrage"></param>/// <returns>彈幕持續(xù)5秒</returns>public static int Line(GameBarrage barrage){barrage.CreateLine(false, 0, 0, 50, new Vector2(25, 0), new Vector2(25, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 1, 50, new Vector2(75, 0), new Vector2(75, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 2, 50, new Vector2(125, 0), new Vector2(125, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 3, 50, new Vector2(175, 0), new Vector2(175, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 4, 50, new Vector2(225, 0), new Vector2(225, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 5, 50, new Vector2(275, 0), new Vector2(275, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 6, 50, new Vector2(325, 0), new Vector2(325, 400), 100, 0, 15, 0);barrage.CreateLine(false, 0, 0, 50, new Vector2(375, 0), new Vector2(375, 400), 100, 0, 15, 0);return 5;}/// <summary>/// 連續(xù)兩撥錯開的扇形彈幕/// </summary>/// <param name="barrage"></param>/// <param name="position"></param>/// <returns>彈幕持續(xù)時間2秒</returns>public static int TwoFans(GameBarrage barrage, Vector2 position){barrage.CreateRotateAndShoot(false, 0, 0, position, 45, 135, 300, 0, 5, 0, 0);barrage.CreateRotateAndShoot(false, 0, 0, position, 43, 143, 300, 0, 5, 0, 0.1f);return 2;}/// <summary>/// 左右兩邊出現(xiàn)相反的漩渦型彈幕/// </summary>/// <param name="barrage"></param>/// <param name="position"></param>/// <returns>彈幕持續(xù)時間4秒</returns>public static int TwoReverseRotate(GameBarrage barrage, Vector2 position){barrage.CreateRotateAndShoot(false, 2, 0, new Vector2(50, position.Y), 0, 180, 350, -80, 8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 4, new Vector2(50, position.Y), 90, 270, 350, -80, 8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 0, new Vector2(50, position.Y), 180, 360, 350, -80, 8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 4, new Vector2(50, position.Y), 270, 450, 350, -80, 8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 0, new Vector2(350, position.Y), 180, 0, 350, -80, -8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 4, new Vector2(350, position.Y), 270, 90, 350, -80, -8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 0, new Vector2(350, position.Y), 360, 180, 350, -80, -8, 1, 0);barrage.CreateRotateAndShoot(false, 2, 4, new Vector2(350, position.Y), 450, 270, 350, -80, -8, 1, 0);return 4;}/// <summary>/// 三個園型彈幕/// </summary>/// <param name="barrage"></param>/// <param name="position"></param>/// <returns>彈幕持續(xù)時間5秒</returns>public static int ThreeCircle(GameBarrage barrage, Vector2 position){barrage.CreateCircle(false, 0, 0, position, 250, 0, 10, 0);barrage.CreateCircle(false, 0, 1, position + new Vector2(-100, 50), 250, 0, 10, 0);barrage.CreateCircle(false, 0, 2, position + new Vector2(100, 50), 250, 0, 10, 0);barrage.CreateCircle(false, 0, 3, position, 250, 0, 10, 0.5f);barrage.CreateCircle(false, 0, 4, position + new Vector2(-100, 50), 250, 0, 10, 0.5f);barrage.CreateCircle(false, 0, 5, position + new Vector2(100, 50), 250, 0, 10, 0.5f);return 5;}}
代碼很多,只是通過一些數(shù)學(xué)計算,產(chǎn)生不同效果而已~~大家可以自由發(fā)揮~~
總結(jié)
以上是生活随笔為你收集整理的基于C#弹幕类射击游戏的实现——(七)弹幕类实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数学通道的应用(四)-发动机转速曲线
- 下一篇: c# char unsigned_dll