今回はキャラクタと会話する方法を考えます。
まずフォームにLabelを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); DoubleBuffered = true; InitDungeons(); _map = mapCastle; mapCastle.BgmStart(); mapCastle.SetPlayerQueen(); label1.Visible = false; } } |
Contents
MapCastleクラスにメソッドを追加
SetPlayerQueenメソッドはプレイヤーを王女の前に配置するためのメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class MapCastle : Map { public void SetPlayerQueen() { int column = 0; int row = 0; this.GetRowColumnFromChar(MapText, '王', ref column, ref row); if (column != -1) { PlayerPoint.X = column * Block.Width; PlayerPoint.Y = (row + 2) * Block.Height; } } } |
ShowMessageイベントの定義
MapCastleクラス内でイベントを定義します。プレイヤーが移動して他のキャラクタと接触したら会話できるようにします。
1 2 3 4 5 |
class MapCastle : Map { public event ShowMessageHandler ShowMessage; public delegate void ShowMessageHandler(object sender, ShowMessageArgs e); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class ShowMessageArgs : EventArgs { public ShowMessageArgs(string message) { Message = message; } public string Message { private set; get; } } |
魔王と接触したら戦闘がはじまるようにします。
1 2 3 4 |
class MapCastle : Map { public event EventHandler BeginBattleBoss; } |
MovePlayerメソッドの修正
あとは城のなかでプレイヤーが移動して他のキャラクタと接触したときにイベントが発生するようにします。
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 |
class MapCastle : Map { public override void MovePlayer(Direct direct) { // 城から出たときのイベント(既出) if (direct == Direct.Down) { if (IsExit(PlayerPoint.X, PlayerPoint.Y)) { BgmStop(); ExitCastle?.Invoke(this, new EventArgs()); return; } } // 王女と接触したら会話がはじまる if ( (direct == Direct.Up && IsQueen(PlayerPoint.X, PlayerPoint.Y - 4)) || (direct == Direct.Down && IsQueen(PlayerPoint.X, PlayerPoint.Y + 4)) || (direct == Direct.Left && IsQueen(PlayerPoint.X - 4, PlayerPoint.Y)) || (direct == Direct.Right && IsQueen(PlayerPoint.X + 4, PlayerPoint.Y)) ) { ShowQueenMessage(); return; } // 魔王と接触したら戦闘がはじまる if ( (direct == Direct.Up && IsDevil(PlayerPoint.X, PlayerPoint.Y - 4)) || (direct == Direct.Down && IsDevil(PlayerPoint.X, PlayerPoint.Y + 4)) || (direct == Direct.Left && IsDevil(PlayerPoint.X - 4, PlayerPoint.Y)) || (direct == Direct.Right && IsDevil(PlayerPoint.X + 4, PlayerPoint.Y)) ) { ShowDevilMessage(); return; } base.MovePlayer(direct); } } |
ShowMessageイベントを発生させる
ShowQueenMessageメソッドとShowDevilMessageメソッドが呼び出されるとイベントが発生します。王女に対しては最初に話しかけたときとそれ以降では内容を変えています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class MapCastle : Map { int QueenMessageCount = 0; string[] QueenMessages = { "王女:勇者さま。お願いです。東の城にいる魔王を倒してください。\n" + "体力を消耗したら私のもとに戻ってきてください。\nけっして無理はなさらぬように。", "王女:勇者さまの健闘をお祈りします。\n" + "勇者の体力が全回復した。", }; // 最初に話しかけたときとそれ以降では内容を変える void ShowQueenMessage() { ShowMessage?.Invoke(this, new ShowMessageArgs(QueenMessages[QueenMessageCount])); if (QueenMessageCount == 0) QueenMessageCount++; } void ShowDevilMessage() { BgmStop(); BeginBattleBoss.Invoke(this, new EventArgs()); } } |
Form1クラスにおける処理
Form1クラスにおける処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { void InitDungeons() { map1 = new Map1(this); map1.EnterCastle += Map1_EnterCastle; map1.EnterEnemyCastle += Map1_EnterEnemyCastle; mapCastle = new MapCastle(this, 0); mapCastle.ExitCastle += MapCastle1_ExitCastle; mapCastle.ShowMessage += MapCastle_ShowMessage; // 王女に話しかけたとき mapEnemyCastle = new MapCastle(this, 1); mapEnemyCastle.ExitCastle += MapCastle1_ExitCastle; mapEnemyCastle.BeginBattleBoss += MapEnemyCastle_BeginBattleBoss; // 魔王との戦闘開始 } } |
キーを押すたびに会話内容が表示される
MapCastle_ShowMessageメソッドが実行されたら会話を表示します。会話は複数回ボタンをおさないと全部表示されない場合があります。その場合はフィールド変数Messagesに格納してひとつずつ出しながら表示します。
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 { List<string> Messages = new List<string>(); private void MapCastle_ShowMessage(object sender, ShowMessageArgs e) { ShowMessageOnMapCastle(e); } void ShowMessageOnMapCastle(ShowMessageArgs e) { // 会話が完了していない場合は新しい会話のイベントは始まらない if (Messages.Count > 0) return; // 複数回にわかれている場合は改行で区切られて渡されるので改行で分割する // 最初のひとつだけを表示する string[] vs = e.Message.Split('\n'); label1.Text = vs[0]; label1.Visible = true; isKeyDown = true; // ふたつめ以降があるならMessagesに格納する if(vs.Length > 1) Messages.AddRange(vs.Skip(1)); } } |
キーを押したときにMessagesに会話内容が格納されていた場合はそれを表示させます。
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 |
public partial class Form1 : Form { // いまはエンディング(ゲームクリア)状態か? bool isEnding = false; protected override void OnKeyDown(KeyEventArgs e) { // エンディングならキー操作無効にする if (isEnding) return; // 会話内容があるなら表示する if(OnKeyDownShowMessage()) return; if (_map != null) { if (e.KeyCode == Keys.Left) _map.MovePlayer(Direct.Left); if (e.KeyCode == Keys.Up) _map.MovePlayer(Direct.Up); if (e.KeyCode == Keys.Right) _map.MovePlayer(Direct.Right); if (e.KeyCode == Keys.Down) _map.MovePlayer(Direct.Down); Invalidate(); } base.OnKeyDown(e); } } |
OnKeyDownShowMessageメソッドが実行されたらMessagesに文字列が格納されていたら表示します。格納されていない場合で会話内容を表示するためのLabelが表示されている場合は非表示にします。いずれでもない場合はこのメソッドはなにもせずにfalseを返します。
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 |
public partial class Form1 : Form { // キーを押しっぱなしにしているときに処理が連続しておこなわれるのを防ぐ bool isKeyDown = false; // 戦闘終了を示すフラグ bool isLastBattle = false; protected override void OnKeyUp(KeyEventArgs e) { isKeyDown = false; base.OnKeyUp(e); } bool OnKeyDownShowMessage() { // 会話内容があるならLabelに表示する if (Messages.Count > 0) { if (!isKeyDown) { isKeyDown = true; string str = Messages[0]; label1.Text = str; label1.Visible = true; Messages.RemoveAt(0); } return true; } // 会話内容がないなら会話表示用のLabelを非表示に if (Messages.Count == 0 && label1.Visible) { if (!isKeyDown) { isKeyDown = true; label1.Visible = false; // 戦闘終了のメッセージが表示されたときの処理(次回) if (isLastBattle) { isLastBattle = false; Battle1_Finished(); } } return true; } return false; } } |