マップを表示させます。マップに表示させるのは自機の位置と敵要塞の位置だけです。それから敵編隊が存在する場合はそれも表示させるのですが、敵編隊自体をプログラミングするかどうかは未定です。
自機の座標と要塞の座標をBitmapにして表示させます。このときOpenTKの座標とBitmapの座標はY座標が逆なのでBitmapを上下反転させています。
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 |
public partial class Form1 : Form { void UpdateMap() { Bitmap bitmap = new Bitmap(200, 320); Graphics g = Graphics.FromImage(bitmap); g.Clear(Color.Blue); g.FillRectangle(new SolidBrush(Color.White), new Rectangle((int)Jiki.X * 2, (int)Jiki.Y * 2, 5, 5)); foreach (Fortress fortress in Fortresses) { if(!fortress.IsDead) g.FillRectangle(new SolidBrush(Color.LightGreen), new Rectangle((int)fortress.X * 2, (int)fortress.Y * 2, 5, 5)); } g.Dispose(); Image oldImage = pictureBox1.Image; bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); pictureBox1.Image = bitmap; if (oldImage != null) oldImage.Dispose(); } } |
マップの端にきたら反対側にワープします。自機が移動できる範囲をX座標は0~100、Y座標を0~160にしています。これを超えたら適切な値を加えたり引いたりして調整しています。このとき移動している敵もいっしょにワープさせます。
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 partial class Form1 : Form { void WarpIfNeed() { if (Jiki.X < 0) { Jiki.X += Config.FieldWidth; Enemies.Select(x => x.X += Config.FieldWidth).ToList(); FortressesBurrets.Select(x => x.X += Config.FieldWidth).ToList(); } else if (Jiki.X > Config.FieldWidth) { Jiki.X -= Config.FieldWidth; Enemies.Select(x => x.X -= Config.FieldWidth).ToList(); FortressesBurrets.Select(x => x.X -= Config.FieldWidth).ToList(); } if (Jiki.Y < 0) { Jiki.Y += Config.FieldHeight; Enemies.Select(x => x.Y += Config.FieldHeight).ToList(); FortressesBurrets.Select(x => x.Y += Config.FieldHeight).ToList(); } else if (Jiki.Y > Config.FieldHeight) { Jiki.Y -= Config.FieldHeight; Enemies.Select(x => x.Y -= Config.FieldHeight).ToList(); FortressesBurrets.Select(x => x.Y -= Config.FieldHeight).ToList(); } } } |
あとはUpdate()メソッドのなかで上記メソッドを呼び出せばマップが表示され、自機が端にきたときは反対側にワープさせることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { new void Update() { MoveJiki(); UpdateBurrets(); CreateEnemyIfNeed(); UpdateEnemies(); FortressesUpdate(); FortressesBurretsUpdate(); HitJudge(); UpdateExplosions(); RemoveOutOfSightObject(); WarpIfNeed(); UpdateMap(); UpdateCount++; } } |
追記
敵の要塞がマップの端近くにある場合、自機がワープすることで消えてしまう場合があります。敵機は基本的に自機の周辺にしか存在しない仕様になっているため、自機といっしょにワープさせてしまえば表示も当たり判定も問題ありませんが、要塞のような位置が固定された敵の場合はそうはいきません。
そこでマップ内の上下左右にコピーをつくって表示させます。これだけでは当たり判定がうまくいかないので、当たり判定に関するメソッドを書き直す必要があります。
まずは要塞の描画にかんする部分です。
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 |
public partial class Form1 : Form { void DrawFortresses() { foreach (Fortress fortress in Fortresses) { if (fortress.IsDead) continue; fortress.Draw(); GL.PushMatrix(); { GL.Translate(Config.FieldWidth, 0, 0); fortress.Draw(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(-Config.FieldWidth, 0, 0); fortress.Draw(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(0, Config.FieldHeight, 0); fortress.Draw(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(0, -Config.FieldHeight, 0); fortress.Draw(); } GL.PopMatrix(); } } } |
次に敵要塞との当たり判定にかんする部分を示します。自機弾丸のコピーを実際に存在する場所の上下左右4箇所につくります。そのなかでX座標が0~FieldWidth、Y座標が0~FieldHeightのものを当たり判定の対象にしています。
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 |
public class Fortress : Character { bool IsCoreHited(Burret burret) { float burretX; float burretY; if (0 < burret.X && burret.X < Config.FieldWidth) burretX = burret.X; else if (0 > burret.X) burretX = burret.X + Config.FieldWidth; else burretX = burret.X - Config.FieldWidth; if (0 < burret.Y && burret.Y < Config.FieldHeight) burretY = burret.Y; else if (0 > burret.Y) burretY = burret.Y + Config.FieldHeight; else burretY = burret.Y - Config.FieldHeight; double distance1 = Math.Sqrt(Math.Pow(X - burretX, 2) + Math.Pow(Y - burretY, 2)); double distance2 = Config.FortressCoreRadius + burret.Radius; if (distance1 < distance2 +1f && (IsVertical && Math.Round(burret.VecX) == 0) || (!IsVertical && Math.Round(burret.VecY) == 0)) return true; return false; } bool IsCannonHited(Burret burret, Cannon cannon) { float burretX; float burretY; if (0 < burret.X && burret.X < Config.FieldWidth) burretX = burret.X; else if(0 > burret.X) burretX = burret.X + Config.FieldWidth; else burretX = burret.X - Config.FieldWidth; if (0 < burret.Y && burret.Y < Config.FieldHeight) burretY = burret.Y; else if (0 > burret.Y) burretY = burret.Y + Config.FieldHeight; else burretY = burret.Y - Config.FieldHeight; double distance1 = Math.Sqrt(Math.Pow(cannon.X - burretX, 2) + Math.Pow(cannon.Y - burretY, 2)); double distance2 = Config.FortressCoreRadius + burret.Radius; if(distance2 > distance1) { return true; } return false; } } |