今回はゲームオーバー処理、万引きがバレて警察署に連行されるシーンの処理を実装します。
Contents
警備員が少年を捕まえる処理
店内で万引きをしているときはTimer.TickイベントがおきるたびにDrawStoreField1メソッドが呼び出されます。その最後の部分を再掲します。
見つかったかどうかの判定
dangerXは警備員から少年の姿がみえるかもしれないX座標です。双方のX座標がdangerXのどれかと一致していてその差の絶対値が4に満たない場合、少年は警備員にみつかったことになります。するとシーンはScene.Store2に変更されます。このシーンでは警備員が少年がいる位置まで下がってきて「コラ!」といって少年を捕まえます。
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 |
public partial class Form1 : Form { void DrawStoreField1() { // 途中省略 int[] dangerX = { 1, 2, 3, 4, 9, 10, 11, 12, 17, 18, 19, 20, 25, 26, 27, 28, 33, 34, 35, 36 }; bool danger = dangerX.Any(x => x == PositionBoyX); bool find = dangerX.Any(x => x == PositionK); if (danger && find && Math.Abs(PositionK - PositionBoyX) < 4) _scene = Scene.Store2; else if (_time < 0) { // 時間切れ 少年を見つかる位置に移動させる PositionBoyX = 18; PositionBoyY = 16; _scene = Scene.Store2; } RedrawStoreField(); _time -= 0.5; SetNewScoreString(); } } |
シーンがScene.Store2のときはTimer.TickイベントがおきるたびにDrawStoreField2メソッドが呼び出されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { private void Timer1_Tick(object sender, EventArgs e) { if (_scene == Scene.Opening) DrawStart(); else if (_scene == Scene.Store1) DrawStoreField1(); else if (_scene == Scene.Store2) DrawStoreField2(); else if (_scene == Scene.Police) DrawPolice(); else if (_scene == Scene.Clear) DrawGameClear(); } } |
警備員を下に移動させる
DrawStoreField2メソッドの処理を示します。引数つきのGetStringDrawKメソッドは引数に警備員を表示させたいY座標を指定します。FieldStringに取得された文字が格納されますが、少年と警備員の足に半角文字を使用しているのでそのあと半角文字に置換しています。
警備員が下に移動するときはTimer.Intervalを150にセットし、移動するたびに効果音を出します。そして警備員が少年よりちょっと上まで移動してきたら「コラ!」の文字を表示させ、別の効果音を出します。ここからKKoraUpdateCountをインクリメントしていき5を超えたらシーンをScene.Policeに変更します。
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 |
public partial class Form1 : Form { void DrawStoreField2() { PositionK = PositionBoyX; FieldString = GetStringDrawBoy(GetStringItems(GetStringDrawK(PositionKY)), false, false); // 足は半角文字を使用するのでここで置き換える FieldString = FieldString.Replace("足", "||▊"); FieldString = FieldString.Replace("脚", "||"); FieldString = FieldString.Replace("▊ ", "▊ "); Invalidate(); SetNewScoreString(); if (PositionKY + 3 < PositionBoyY) { Timer1.Interval = 150; PositionKY++; Sound2(); } else { char[] vs = FieldString.ToCharArray(); int index = (PositionKY-1) * ColumMax +PositionK; vs[index] = ' '; vs[index + 1] = 'コ'; vs[index+2] = 'ラ'; vs[index + 3] = '!'; vs[index + 4] = '!'; List<char> a = new List<char>(vs); a.Insert(index + 5, ' '); a.Insert(index + 6, ' '); FieldString = new string(a.ToArray()); KKoraUpdateCount++; if (KKoraUpdateCount == 1) Sound3(); if (KKoraUpdateCount > 5) { KKoraUpdateCount = 0; _scene = Scene.Police; } } } } |
警備員を下に移動させる引数つきのGetStringDrawKメソッドを示します。
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 { string GetStringDrawK(int row) { char[] vs = StoreField.ToCharArray(); int index1 = ColumMax * (row + 0); int index2 = ColumMax * (row + 1); int index3 = ColumMax * (row + 2); vs[index1 + 1 + PositionK] = '●'; vs[index2 + 0 + PositionK] = '('; vs[index2 + 1 + PositionK] = '■'; vs[index2 + 2 + PositionK] = ')'; vs[index3 + 1 + PositionK] = '脚'; LastPositionK = PositionK; return new string(vs); } } |
これは効果音を出すための処理です。短い間隔で効果音を出そうとすると実際に音がでる前に次の音を出そうとしてなにも音がでないのでその都度WMPLib.WindowsMediaPlayerオブジェクトを生成しています。「コラ!」というときに再生される効果音は1回だけなのですでにフィールド変数として宣言されているオブジェクトをつかって効果音を再生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { void Sound2() { WMPLib.WindowsMediaPlayer mediaPlayer2 = new WMPLib.WindowsMediaPlayer(); mediaPlayer2.settings.autoStart = true; mediaPlayer2.URL = Application.StartupPath + "\\k-move-down.mp3"; } WMPLib.WindowsMediaPlayer</h2> mediaPlayer = new WMPLib.WindowsMediaPlayer(); void Sound3() { mediaPlayer.settings.autoStart = true; mediaPlayer.URL = Application.StartupPath + "\\kora.mp3"; } } |
警察署に連行されるゲームオーバー時の処理
シーンがScene.PoliceのときにTimer.Tickイベントが発生したらDrawPoliceメソッドが実行されます。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { void DrawPolice() { FieldString = GetGameOverString(); Invalidate(); } } |
GetGameOverStringメソッドは以下のようになっています。ここではスコアを表示させる文字列を取得するとともに警備員によって警察署に連行される少年のアスキーアートと歩く音をならし、この関数を一定回数表示したら少年を土下座させたり、「PUSH S KEY GAME START!」の文字を表示させます。
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 { string GetGameOverString() { string s = String.Format("{0:000000}", _score); s = s.Replace("0", "0"); s = s.Replace("1", "1"); s = s.Replace("2", "2"); s = s.Replace("3", "3"); s = s.Replace("4", "4"); s = s.Replace("5", "5"); s = s.Replace("6", "6"); s = s.Replace("7", "7"); s = s.Replace("8", "8"); s = s.Replace("9", "9"); GameOverUpdateCount++; string str; if (GameOverUpdateCount < 10) { if(GameOverUpdateCount == 1) SoundGameOver(); str = GetGameOverString1(); } else { str = GetGameOverString2(); } // GameOverUpdateCountが31以下のときは「PUSH S KEY GAME START!」を表示させない if(GameOverUpdateCount < 32) str = str.Replace("PUSH S KEY GAME START!", ""); return str.Replace("000000", s); } } |
GetGameOverString1メソッドは少年が連行される様子を示す文字列を取得します。GetGameOverString1メソッドが呼び出されるたびに少年と警備員の表示位置を左へ移動させます。
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 |
public partial class Form1 : Form { string GetGameOverString1() { char[] vs = PoliceField.ToCharArray(); int update = GameOverUpdateCount; // 警備員が少年を連行する様子を示す文字に入れ替える int row = 11; vs[ColumMax * row + 32 - update] = '_'; vs[ColumMax * row + 32 + 1 - update] = '●'; vs[ColumMax * row + 32 + 4 - update] = '○'; row = 12; vs[ColumMax * row + 32 + 1 - update] = '■'; vs[ColumMax * row + 32 + 2 - update] = '■'; vs[ColumMax * row + 32 + 3 - update] = '✕'; vs[ColumMax * row + 32 + 4 - update] = '■'; vs[ColumMax * row + 32 + 5 - update] = '■'; row = 13; vs[ColumMax * row + 32 + 1 - update] = '〈'; vs[ColumMax * row + 32 + 2 - update] = '〈'; vs[ColumMax * row + 32 + 4 - update] = '〈'; vs[ColumMax * row + 32 + 5 - update] = '〈'; return new string(vs); } } |
少年を土下座させる
GetGameOverString2メソッドは少年を土下座させる文字列を取得する処理をおこなっています。
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 { string GetGameOverString2() { char[] vs = PoliceField.ToCharArray(); int row = 9; vs[ColumMax * row + 22] = 'コ'; vs[ColumMax * row + 23] = 'ラ'; vs[ColumMax * row + 24] = '!'; vs[ColumMax * row + 25] = '!'; row = 11; vs[ColumMax * row + 22] = '●'; if (GameOverUpdateCount % 2 == 0) vs[ColumMax * row + 23] = '_'; vs[ColumMax * row + 25] = 'ウ'; vs[ColumMax * row + 26] = 'ヘ'; vs[ColumMax * row + 27] = 'ェ'; row = 12; vs[ColumMax * row + 22] = '■'; if(GameOverUpdateCount % 2 == 1) vs[ColumMax * row + 23] = '\'; vs[ColumMax * row + 26] = '/'; row = 13; vs[ColumMax * row + 22] = '▎'; vs[ColumMax * row + 23] = '▎'; vs[ColumMax * row + 25] = '○'; vs[ColumMax * row + 26] = 'r'; vs[ColumMax * row + 27] = 'z'; return new string(vs); } } |
ゲームオーバー時の効果音を鳴らすメソッドです。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { void SoundGameOver() { mediaPlayer.settings.autoStart = true; mediaPlayer.URL = Application.StartupPath + "\\gameover.mp3"; } } |
ゲームに再挑戦できるようにする
ゲームオーバーになって一定時間が経過(GameOverUpdateCount >= 32)するともう一度ゲームをすることができるようにします。Sキーを押すとオープニングのシーンに戻り、ゲームが初期化(スコアのリセット、その他フィールド変数の初期化など)され、ゲームが再開されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { bool OnKeyDownGameRetry(KeyEventArgs e) { if (e.KeyCode == Keys.S) { if (_scene == Scene.Police && GameOverUpdateCount >= 32) { _scene = Scene.Opening; InitGame(); return true; } } return false; } } |