で敵を作りましたが、表示の確認用のものであり、ぜんぜん敵らしくありませんでした。そこで今回は敵らしい敵をつくります。敵は2種類で原作のものを使います。
アイヒ型ミサイル
自機をしつこく追跡する。50点。
プルーア型ミサイル
自機を囲みながら攻撃してくる。60点。
ほかにも
エッドール型ミサイル
ステージ4以降から登場。敵基地中心部から発射される。70点。
偵察機
ステージ4以降から登場。画面外に逃げられるとコンディションレッドまでの時間が短縮される。
さらに固定敵として
小惑星
自機・敵機問わず接触すると破壊される。10点。
機雷
破壊すると爆発し、近くにいると自機・敵機問わず誘爆に巻き込まれ破壊される。20点。
このような敵もあるのですが今回は省略します。
リソースに以下のようなものを追加します。
敵クラスをつくります。Enemy1とEnemy2の違いは動き方です。Enemy1は移動速度が遅く(自機より遅い)、方向転換を短い間隔でおこないます。Enemy2は移動速度が自機よりも速く、反面方向転換はEnemy1よりも頻繁にはおこないません。また移動方向によって向きが変わります。
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
using OpenTK; using OpenTK.Graphics.OpenGL; class Enemy1 : EnemyBase { public Enemy1(Form1 form1, float x, float y, float vecX, float vecY) : base(form1, x, y, vecX, vecY) { if (Textures.Count == 0) Textures = CreateTextures(); Radius = Config.EnemyRadius; } static List<int> Textures = new List<int>(); protected override List<Bitmap> GetBitmaps() { List<Bitmap> bitmaps = new List<Bitmap>(); Bitmap bitmap = Properties.Resources.enemy1; bitmap.MakeTransparent(); bitmaps.Add(bitmap); return bitmaps; } public override void Update() { // 実際にプレイしてみてわかったが、 // int a = 10; float sppedRate = 1.5f; で // ほぼ無理ゲーとなる int a = 10; if(UpdateCount % a == 0) { JikiInfo info = MainForm.GetJikiInfo(); float jiki_vx = info.VecX; float jiki_vy = info.VecY; double dx = (info.X - X + jiki_vx * a * info.Speed); double dy = (info.Y - Y + jiki_vy * a * info.Speed); double angle = Math.Atan2(dy, dx); VecX = (float)Math.Cos(angle) * Config.EnemySpeedA; VecY = (float)Math.Sin(angle) * Config.EnemySpeedA; } base.Update(); } public override void Draw() { double rad = Math.Atan2((Double)VecY, (Double)VecX); double angle = rad / (2 * Math.PI) * 360; GL.BindTexture(TextureTarget.Texture2D, Textures[0]); 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(0, 1); GL.Vertex3(-Radius, Radius, 0); GL.TexCoord2(0, 0); GL.Vertex3(-Radius, -Radius, 0); GL.TexCoord2(1, 0); GL.Vertex3(Radius, -Radius, 0); } GL.End(); } GL.PopMatrix(); GL.BindTexture(TextureTarget.Texture2D, 0); } } |
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
using OpenTK; using OpenTK.Graphics.OpenGL; class Enemy2 : EnemyBase { public Enemy2(Form1 form1, float x, float y, float vecX, float vecY) : base(form1, x, y, vecX, vecY) { if (Textures.Count == 0) Textures = CreateTextures(); Radius = Config.EnemyRadius; } static List<int> Textures = new List<int>(); protected override List<Bitmap> GetBitmaps() { List<Bitmap> bitmaps = new List<Bitmap>(); Bitmap bitmap = Properties.Resources.enemy2; bitmap.MakeTransparent(); bitmaps.Add(bitmap); return bitmaps; } public override void Update() { int a = 20; if (UpdateCount % a == 0) { JikiInfo info = MainForm.GetJikiInfo(); float jiki_vx = info.VecX; float jiki_vy = info.VecY; double dx = (info.X - X + jiki_vx * a * info.Speed); double dy = (info.Y - Y + jiki_vy * a * info.Speed); double angle = Math.Atan2(dy, dx); float sppedRate = 1.2f; VecX = (float)Math.Cos(angle) * Config.EnemySpeedB; VecY = (float)Math.Sin(angle) * Config.EnemySpeedB; } base.Update(); } public override void Draw() { double rad = Math.Atan2((Double)VecY, (Double)VecX); double angle = rad / (2 * Math.PI) * 360; GL.BindTexture(TextureTarget.Texture2D, Textures[0]); 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(0, 1); GL.Vertex3(-Radius, Radius, 0); GL.TexCoord2(0, 0); GL.Vertex3(-Radius, -Radius, 0); GL.TexCoord2(1, 0); GL.Vertex3(Radius, -Radius, 0); } GL.End(); } GL.PopMatrix(); GL.BindTexture(TextureTarget.Texture2D, 0); } } |
敵を作ったら戦闘に参加させます。Form1.Update()メソッドのなかで敵を生成する必要があるのであれば敵を生成してリストに加えます。敵の最大数は10個です。
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 |
public partial class Form1 : Form { List<EnemyBase> Enemies = new List<EnemyBase>(); Random Random = new Random(); new void Update() { MoveJiki(); UpdateBurrets(); CreateEnemyIfNeed(); UpdateEnemies(); FortressesUpdate(); FortressesBurretsUpdate(); HitJudge(); UpdateExplosions(); RemoveOutOfSightObject(); WarpIfNeed(); UpdateMap(); if (DateTime.Now > bgmEndTime) PlayBGM1(); UpdateCount++; } void CreateEnemyIfNeed() { if (UpdateCount % 60 == 0 && Enemies.Count < Config.MaxEnemiesCount) { int angle = Random.Next(360); double rad = angle * Math.PI / 180; float x = Jiki.X + 30 * (float)Math.Cos(rad); float y = Jiki.Y + 30 * (float)Math.Sin(rad); int kind = Random.Next(2); if(kind == 0) Enemies.Add(new Enemy1(this, x, y, 0, 0, 1, 1)); if (kind == 1) Enemies.Add(new Enemy2(this, x, y, 0, 0, 1, 1)); } } } |
実際にプレイしてみると原作のボスコニアンより難しいです。原作のボスコニアンは方向転換したい方向にレバーを倒せばすぐにできましたが、このゲームでは自機の方向転換を自由にできません。この部分は改善する必要がありそうです。