この講座はシミュレーションRPGの作り方について説明しています。今回はその第6回目になります。
前回はSRPGに必須のマップ上の移動用ブロックのマス表示処理やあるマスを選択した状態で別のマスを選択すると元々選択していたマスを非表示にする処理を実装しました。
前回の記事:
マップのブロックを選択できるようになったので、今回はこれを発展させて選択地点のキャラクターを取得して移動させる処理までを実装していきましょう。
選択地点のキャラクターを取得する
ブロックをタップで選択した時に、そのブロックと同じ位置にいるキャラクターのデータ(Characterクラス)を取得する処理がまず必要になります。
これを可能にする為にブロックのデータ(MapBlockクラス)内にそのブロックの位置情報を保存させるようにしましょう。(しなくてもTransformの座標から計算可能ですが、こうした方が容易になります。)
MapBlock.cs内 メンバ変数追加
1 2 3 4 5 |
// ブロックデータ [HideInInspector] // インスペクタ上で非表示にする属性 public int xPos; // X方向の位置 [HideInInspector] public int zPos; // Z方向の位置 |
- [HideInInspector]属性を付与するとpublicな変数でもInspectorからの編集が不可になります。
MapManager.cs内 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 39 40 41 42 43 44 45 46 47 48 49 |
void Start() { // マップデータを初期化 mapBlocks = new MapBlock[MAP_WIDTH, MAP_HEIGHT]; // ブロック生成位置の基点となる座標を設定 Vector3 defaultPos = new Vector3 (0.0f, 0.0f, 0.0f); // x:0.0f y:0.0f z:0.0f のVector3変数defaultPosを宣言 defaultPos.x = -(MAP_WIDTH / 2); // x座標の基点 defaultPos.z = -(MAP_HEIGHT / 2); // z座標の基点 // ブロック生成処理 for (int i = 0; i < MAP_WIDTH; i++) {// マップの横幅分繰り返し処理 for (int j = 0; j < MAP_HEIGHT; j++) {// マップの縦幅分繰り返し処理 // ブロックの場所を決定 Vector3 pos = defaultPos; // 基点の座標を元に変数posを宣言 pos.x += i; // 1個目のfor分の繰り返し回数分x座標をずらす pos.z += j; // 2個目のfor分の繰り返し回数分z座標をずらす // ブロックの種類を決定 int rand = Random.Range (0, 100); // 0~99の中から1つランダムな数字を取得 bool isGrass = false; // 草ブロック生成フラグ(初期状態はfalse) // 乱数値が草ブロック確率値より低ければ草ブロックを生成する if (rand < GENERATE_RATIO_GRASS) isGrass = true; // オブジェクトを生成 GameObject obj; // 生成するオブジェクトの参照 if (isGrass) {// 草ブロック生成フラグ:ON obj = Instantiate (blockPrefab_Grass, blockParent); // blockParentの子に草ブロックを生成 } else {// 草ブロック生成フラグ:OFF obj = Instantiate (blockPrefab_Water, blockParent); // blockParentの子に水場ブロックを生成 } // オブジェクトの座標を適用 obj.transform.position = pos; // 配列mapBlocksにブロックデータを格納 var mapBlock = obj.GetComponent<MapBlock> (); // オブジェクトのMapBlockを取得 mapBlocks[i, j] = mapBlock; // ブロックデータ設定 mapBlock.xPos = (int)pos.x; // X位置を記録 mapBlock.zPos = (int)pos.z; // Z位置を記録 } } } |
ブロック生成時にそのブロックデータに位置情報を記録するようにします。これはCharacterが持っている位置情報と同じ種類です。
キャラクターに現在位置データを持たせる
次はキャラクター側のスクリプトを編集していきます。
移動処理の実装に先んじて、移動を行った後のキャラクターの位置データを保存する為の変数を用意しておきます。
まだゲーム部分での変化は分かりにくいですが、キャラクター選択後に他のブロックが選択できなくなっているのでちゃんとモードが進行している事が分かります。
タップ地点にキャラクターを移動させる
準備が整いましたので、まずはキャラクターの移動操作を簡易的に実装していきます。Characterクラスに移動処理を作成しましょう。
Character内 新規メソッド
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/// <summary> /// 対象の座標へとキャラクターを移動させる /// </summary> /// <param name="targetXPos">x座標</param> /// <param name="targetZPos">z座標</param> public void MovePosition (int targetXPos, int targetZPos) { // オブジェクトを移動させる // 移動先座標への相対座標を取得 Vector3 movePos = Vector3.zero; // (0.0f, 0.0f, 0.0f)でVector3で初期化 movePos.x = targetXPos - xPos; // x方向の相対距離 movePos.z = targetZPos - zPos; // z方向の相対距離 // 移動処理 transform.position += movePos; // キャラクターデータに位置を保存 xPos = targetXPos; zPos = targetZPos; } |
- 現在の位置から移動先位置への相対座標を計算してtransform.positionに加算しています。
このMovePositionメソッドをGameManagerから呼び出します。
GameManager.cs内 SelectBlockメソッド
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 |
/// <summary> /// 指定したブロックを選択状態にする処理 /// </summary> /// <param name="targetMapBlock">対象のブロックデータ</param> private void SelectBlock (MapBlock targetBlock) { // 現在の進行モードごとに異なる処理を開始する switch (nowPhase) { // 自分のターン:開始時 case Phase.MyTurn_Start: // 全ブロックの選択状態を解除 mapManager.AllSelectionModeClear (); // ブロックを選択状態の表示にする targetBlock.SetSelectionMode (true); // 選択した位置に居るキャラクターのデータを取得 var charaData = charactersManager.GetCharacterDataByPos (targetBlock.xPos, targetBlock.zPos); if (charaData != null) {// キャラクターが存在する // 選択中のキャラクター情報に記憶 selectingChara = charaData; // 進行モードを進める:移動先選択中 ChangePhase (Phase.MyTurn_Moving); } break; // 自分のターン:移動先選択中 case Phase.MyTurn_Moving: // 選択中のキャラクターを移動させる selectingChara.MovePosition (targetBlock.xPos, targetBlock.zPos); // 全ブロックの選択状態を解除 mapManager.AllSelectionModeClear (); // 進行モードを進める:移動後のコマンド選択中 ChangePhase (Phase.MyTurn_Command); break; } } |
まとめ
これによって選択したキャラクターが移動するようになりました。
しかし、現在の仕様ではマップ内のどのブロックに対しても制限なく移動できてしまいます。シミュレーションRPGとしては移動範囲の制限が必要になりますので次回はその要素を実装しましょう。
次の記事:
コメント