前回は要塞の描画と当たり判定に関する処理をしました。今回は要塞から弾丸を発射させます。弾丸は自機が接近したときに破壊されていない砲台から発射されます。またコアのむこう側にある砲台からは発射されません。
自機が要塞のコアからみて要塞の半径の5倍の距離よりも近い距離に存在する場合、その距離よりも近い位置にある砲台で破壊されていないものから自機がある方向にむけて発射されます。弾丸の移動速度は自機より少し遅くします(そうでないと無理ゲーになる)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public class Fortress : Character { static Random Random = new Random(); public override void Update() { // 1000 / 60 * 50 msごとに発射するか判断する if (UpdateCount % 50 == 0) { JikiInfo jikiInfo = MainForm.GetJikiInfo(); double distanceFromCore = Math.Sqrt(Math.Pow(jikiInfo.X - X, 2) + Math.Pow(jikiInfo.Y - Y, 2)); if (Radius * 5 > distanceFromCore) { List<Cannon> cannons = Cannons.Where(x => !x.IsDead && Math.Sqrt(Math.Pow(jikiInfo.X - x.X, 2) + Math.Pow(jikiInfo.Y - x.Y, 2)) < distanceFromCore).ToList(); { foreach (Cannon cannon in cannons) { // 条件を満たしている場合、1/2の確率で発射する if(Random.Next(2) == 0) { double rad = Math.Atan2(jikiInfo.Y - cannon.Y, jikiInfo.X - cannon.X); MainForm.FortressesBurrets.Add(new FortressBurret(MainForm, cannon.X, cannon.Y, jikiInfo.Speed * (float)Math.Cos(rad) * 0.8f, jikiInfo.Speed * (float)Math.Sin(rad) * 0.8f, 0.2f, 1)); } } } } } base.Update(); } } |
以下は要塞から発射された弾丸を描画するためのクラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
using OpenTK; using OpenTK.Graphics.OpenGL; public class FortressBurret : Character { public FortressBurret(Form1 form1, float x, float y, float vecX, float vecY) : base(form1, x, y, vecX, vecY) { Radius = Config.FortressBurretRadius; if (Textures.Count == 0) Textures = CreateTextures(); } static List<int> Textures = new List<int>(); protected override List<Bitmap> GetBitmaps() { Bitmap bitmap = Properties.Resources.sprite2; List<Bitmap> bitmaps = new List<Bitmap>(); bitmaps.Add(GetBitmap(new Size(8, 8), new Point(32, 49), new Size(8, 8))); bitmaps.Add(GetBitmap(new Size(12, 12), new Point(42, 47), new Size(12, 12))); return bitmaps; } public override void Draw() { double rad = Math.Atan2(VecY, VecX); double angle = 180 * rad / Math.PI; Radius = Config.FortressBurretRadius; if (UpdateCount % 8 < 4) GL.BindTexture(TextureTarget.Texture2D, Textures[0]); else { GL.BindTexture(TextureTarget.Texture2D, Textures[1]); Radius *= 1.5f; } GL.PushMatrix(); { GL.Translate(X, Y, 0); GL.Rotate(angle - 90, 0, 0, 1); GL.Begin(BeginMode.Quads); { GL.TexCoord2(1, 1); GL.Vertex3(Radius, Radius, 0); GL.TexCoord2(1, 0); GL.Vertex3(Radius, -Radius, 0); GL.TexCoord2(0, 0); GL.Vertex3(-Radius, -Radius, 0); GL.TexCoord2(0, 1); GL.Vertex3(-Radius, Radius, 0); } GL.End(); } GL.PopMatrix(); GL.BindTexture(TextureTarget.Texture2D, 0); } } |
Form1.Update()メソッドに要塞から弾丸を発射する処理を追加します。Fortress.Update()メソッドを実行することで必要であれば要塞から弾丸が発射されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public partial class Form1 : Form { public List<FortressBurret> FortressesBurrets = new List<FortressBurret>(); new void Update() { MoveJiki(); UpdateBurrets(); CreateEnemyIfNeed(); UpdateEnemies(); FortressesUpdate(); FortressesBurretsUpdate(); HitJudge(); UpdateExplosions(); RemoveOutOfSightObject(); if (DateTime.Now > bgmEndTime) PlayBGM1(); UpdateCount++; } // 必要であれば要塞から弾丸が発射される void FortressesUpdate() { foreach (Fortress fortress in Fortresses) fortress.Update(); } // 要塞から発射された弾丸を移動させる void FortressesBurretsUpdate() { foreach (Burret burret in FortressesBurrets) burret.Update(); } } |
あと要塞から発射された弾丸との当たり判定も必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public partial class Form1 : Form { void HitJudge() { ExplosionIfHitEnemies(); ExplosionIfHitFortresses(); ExplosionIfJikiCrashEnemies(); ExplosionIfJikiCrashFortresses(); ExplosionIfJikiCrashFortressesBurrets(); } void ExplosionIfJikiCrashFortressesBurrets() { if (Jiki.IsDead) return; foreach (FortressBurret burret in FortressesBurrets) { double distance = Math.Sqrt(Math.Pow(Jiki.X - burret.X, 2) + Math.Pow(Jiki.Y - burret.Y, 2)); if (Jiki.Radius + burret.Radius > distance) { burret.IsDead = true; JikiDead(); return; } } } void RemoveOutOfSightObject() { Burrets = Burrets.Where(x => GetDistance(x) < 20 && !x.IsDead).ToList(); Enemies = Enemies.Where(x => GetDistance(x) < 40 && !x.IsDead).ToList(); Fortresses = Fortresses.Where(x => !x.IsDead).ToList(); t(); Explosions = Explosions.Where(x => GetDistance(x) < 40 && !x.IsDead).ToList(); // 範囲外に飛んでいった弾丸はリストから外す FortressesBurrets = FortressesBurrets.Where(x => GetDistance(x) < 20 && !x.IsDead).ToLis } } |
あとは描画するだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { void Draw() { DrawFieldLines(); if(!Jiki.IsDead) Jiki.Draw(); DrawBurrets(); DrawEnemies(); DrawFortresses(); DrawFortressesBurrets(); DrawExplosions(); } void DrawFortressesBurrets() { foreach (FortressBurret burret in FortressesBurrets) burret.Draw(); } } |
Major thankies for the post. Really looking forward to read more. Great. Maggie Mile Sandry