この講座はハクスラローグライク×デッキ構築型カードバトルRPG「呪術迷宮」の作り方講座の第12回です。
前回は連続戦闘システム、ステージ進行とプレイヤーカードの発動までを実装しました。
前回の記事:
現状ではプレイヤーが一方的に攻撃するのみですので、戦闘を楽しめるように敵側の攻撃(ターン開始時にプレイボードに敵カードが並ぶ)を実装していきましょう。
更にこのゲームのキモとなるカードの合成機能、そして前回用意できなかった状態異常システムも実装し戦闘をさらに充実させていきます。
また、今回の最後では12章までのスクリプト全文と途中まで開発が完了したサンプルプロジェクトファイルもお付けします(カードデータや敵データ等は追試用に作ったものになるため、サンプルプロジェクトファイルと全く同じになる必要はありません)。
敵側カード設置処理
どの敵がどのカードをどのターンに配置してくるかに関しては第8章で設定済みなので今回やる事はあまり多くありません。
敵のカードは敵グラフィックの上からプレイボード上に移動するアニメーションを行うので、まずは敵グラフィックの位置を取得するメソッドを追加します。
CharacterManager.cs内 各種Get系領域
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 |
#region 各種Get系 /// <summary> /// プレイヤーのHPが0以下であるかを返す /// </summary> /// <returns>プレイヤー敗北フラグ</returns> public bool IsPlayerDefeated () { if (nowHP[Card.CharaID_Player] <= 0) return true; else return false; } /// <summary> /// 敵のHPが0以下であるかを返す /// </summary> /// <returns>敵撃破フラグ</returns> public bool IsEnemyDefeated () { if (nowHP[Card.CharaID_Enemy] <= 0) return true; else return false; } /// <summary> /// 敵画像の座標を返す /// </summary> public Vector2 GetEnemyPosition () { return enemyPicture.transform.position; } #endregion |
そしてFieldManager側でターン開始時に敵カードを全て設置する処理を追加します。
FieldManager.cs内 ゲーム進行処理領域
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
#region ゲーム進行処理 /// <summary> /// 敵との戦闘開始時処理 /// </summary> public void OnBattleStarting () { // デッキデータ取得 playerDeckData = new List<CardDataSO> (); playerDeckData_BackUp = new List<CardDataSO> (); foreach (var cardData in PlayerDeckData.deckCardList) { playerDeckData.Add (PlayerDeckData.CardDatasBySerialNum[cardData]); playerDeckData_BackUp.Add (PlayerDeckData.CardDatasBySerialNum[cardData]); } // デッキ残り枚数表示 PrintPlayerDeckNum (); } /// <summary> /// ターン開始時処理 /// </summary> public void OnTurnStarting () { // カードのドロー枚数決定 int nextHandCardsNum = 5; // 手札枚数 // ドロー処理 DrawCardsUntilNum (nextHandCardsNum); reserveHandAlign = true; // カード実行ボタンを有効化 cardPlayButton.interactable = true; // 敵のカード設置 PlacingEnemyCards (); } /// <summary> /// (ターン開始時)敵側のカードをプレイボードに全て設置する /// </summary> private void PlacingEnemyCards () { // 敵データ取得 var enemyData = battleManager.characterManager.enemyData; // このターンに使用する敵カードセットの番号を取得 int enemyAttackOrderID = battleManager.nowTurns % enemyData.useCardDatas.Count; // 敵カード設置処理 var useCardDatasInThisTurn = enemyData.useCardDatas[enemyAttackOrderID]; // このターンの使用カードリスト for (int i = 0; i < PlayBoardManager.PlayBoardCardNum; i++) { // 各ゾーンに対する設置カードを取得 CardDataSO cardData = null; switch (i) { case 0: cardData = useCardDatasInThisTurn.placeCardData_0; break; case 1: cardData = useCardDatasInThisTurn.placeCardData_1; break; case 2: cardData = useCardDatasInThisTurn.placeCardData_2; break; case 3: cardData = useCardDatasInThisTurn.placeCardData_3; break; case 4: cardData = useCardDatasInThisTurn.placeCardData_4; break; } // 設置カードが無いなら次へ if (cardData == null) continue; // 設置先ゾーンIDを取得 var areaType = CardZone.ZoneType.PlayBoard0 + i; // 設置先Vector2座標を取得 Vector2 targetPosition = battleManager.playBoardManager.GetPlayZonePos (i); // オブジェクト作成 var obj = Instantiate (cardPrefab, cardsParent); // カード処理クラスを取得・リストに格納 Card objCard = obj.GetComponent<Card> (); cardInstances.Add (objCard); // カード初期設定 objCard.Init (this, battleManager.characterManager.GetEnemyPosition ()); // カード出現座標は敵画像と同じ objCard.PutToZone (areaType, targetPosition); objCard.SetInitialCardData (cardData, Card.CharaID_Enemy); // 敵IDを指定 } } /// <summary> /// カード効果発動ボタン押下時処理 /// </summary> public void CardPlayButton () { // カードドラッグ中なら処理しない if (draggingCard != null) return; // 実行ボタンを一時的に無効化 cardPlayButton.interactable = false; // 効果実行処理中フラグ isCardPlaying = true; // プレイボード上カードの配列を作成 Card[] boardCards = new Card[PlayBoardManager.PlayBoardCardNum]; // プレイボード上のカードを取得して配列に格納 foreach (var card in cardInstances) { // 配列内の指定の位置に該当カードを格納する if (card.nowZone >= CardZone.ZoneType.PlayBoard0 && card.nowZone <= CardZone.ZoneType.PlayBoard4) { int arrayID = (int)card.nowZone - (int)CardZone.ZoneType.PlayBoard0; boardCards[arrayID] = card; } } // 各カードの効果を実行 battleManager.playBoardManager.BoardCardsPlay (boardCards); } /// <summary> /// ターン終了時に実行される処理 /// </summary> public void OnTurnEnd () { // 効果実行処理中フラグ isCardPlaying = false; } #endregion |
- 変数宣言時、型を指定する箇所にvarと入力すればスクリプト内で自動的に適した型が割り当てられます。(右辺で初期化を同時に行う場合のみ使用可能な機能です。)
敵データ内に設定されている設置カード情報を取得し、それをもとにカードオブジェクトを生成して設置を行っています。
これで敵が攻撃を行ってくるようになりました。
効果を発動すれば、敵のカードのダメージ効果ではこちらのHPが減少する事を確認できます。
ただし、まだ今のままだと敵カードの上に自分のカードを重ねて戦闘を進めると正しくダメージ計算が行われないなどのバグがありますね。
次は合成機能を実装してこの部分を変更していきましょう。
カードの合成機能を実装する
このゲームにおいて重要なファクターであるカード合成機能を実装していきます。ゲームの戦略性を向上させて敵との熱い駆け引きを楽しめるようにしていきましょう。
カード合成の仕様は以下です。
- プレイボード上のカードに他のプレイヤーカードをドラッグ操作で重ね合わせると合成が行われる
- ドラッグしたカード(素材カード)は合成時に消費される。
- プレイボード上にあったカード(本体カード)は素材カードの持つ効果を受け継ぐ(合成できない効果は除外)。同じ効果があった場合は効果値が加算される。
- 本体カードの強度と素材カードの強度が加算され、強度が10以上になると本体カードも消費される。
ほか、特定条件で合成自体が不可能になるカード効果も存在します。
それではカード処理クラス側から拡張しましょう。
まとめ
敵の攻撃とカード合成という呪術迷宮の戦闘で最も重要となるゲームシステムを開発しました。さらに未実装だった状態異常系のカード効果も実装しました。
この辺りからテストプレイでも敵との駆け引きが楽しめるようになり、呪術迷宮というゲームがどうやって作られていたかがかなりイメージしやすくなったのではないでしょうか。
基本となるゲームシステムが完成に向かいつつあるので引き続き頑張っていきましょう!
次の記事:
コメント