見出し画像

【Unity】3Dローグライクゲームの作り方〜Step9&10-8〜

前回の記事はこちら
前回はサブメニューを開いたり、サブメニューの項目を選べるようにしたりしました。

アイテムをインベントリから削除する

アイテムをインベントリから削除できるようにしたいと思います。という訳で、Inventoryクラスに以下のメソッドを追記しましょう。

/**
* インベントリから指定したアイテムを削除する
*/
public bool Remove(Item it)
{
   if (it != null)
   {
       return items.Remove(it);
   }
   return false;
}

nullでなければ、指定したアイテムを削除するメソッドです。

アイテムを使ったらインベントリから削除する

次に、サブメニューで「使う」を選んだら、アイテムが削除されるようにします。
ActorUseItemsスクリプトを開いて下さい。以下を追加します。

// 以下のデリゲートを追加
public delegate bool UseItem(Item it);

// 以下のメソッドを追加
/**
* 文字列に対応するデリゲートを返す
*/
public UseItem GetDelegate(string method)
{
   switch (method)
   {
       case "Use": return new UseItem(Use);
       case "Put": return new UseItem(Put);
       case "Throw": return new UseItem(Throw);
   }
   return new UseItem(DoNothing);
}

/**
* 引数で渡されたアイテムを使う
*/
public bool Use(Item it)
{
   Message.Add(5, param.actorName, it.name);
   inventory.Remove(it);
   return true;
}

/**
* 引数で渡されたアイテムを置く
*/
public bool Put(Item it)
{
   return true;
}

/**
* 引数で渡されたアイテムを投げる
*/
public bool Throw(Item it)
{
   return true;
}

/**
* 何もしない
*/
public bool DoNothing(Item it)
{
   return true;
}

GetDelegateメソッドは引数で渡された文字列に対応するデリゲートを返します。
ID5番は食べるメッセージです。
今のところはアイテム効果の実装はしません。
次にInventoryActionクラスを以下のように変更します。

// 以下のメソッドを追加
/**
* サブメニューの項目を選択
*/
private void SelectSubMenuItem()
{
   if (Input.anyKeyDown && Input.GetKeyDown(KeyCode.Space))
   {
       action = EAct.Act;
       subMenu.Hide();
   }
}

// 以下のメソッドを変更
private void ActBegin()
{
   if (isCursorMoving)
   {
       isCursorMoving = !MoveSelectItem();
       return;
   }
   if (selectItem == null)
   {
       isCursorMoving = !MoveSelectItem();
       if (isCursorMoving) return;
       KeyInput();
       SelectItem();
   }
   else
   {
       MoveSelectSubMenuItem();
       SelectSubMenuItem(); // これを追記
       UnSelectItem();
   }
}

private void Act()
{
   action = EAct.MoveBegin; // これを追記
}

private void MoveEnd()
{
   if (isOpen) action = EAct.ActBegin;
   else
   {
       gameObject.SetActive(false);
       if(selectItem == null)
       {
           action = EAct.KeyInput;
           return;
       }
       ActorUseItems actorUse = display.inventory.GetComponentInParent<ActorUseItems>();
       ActorUseItems.UseItem use = actorUse.GetDelegate(subMenu.GetSelectItemMethod());
       if (use(selectItem)) {
           selectItem = null;
           action = EAct.ActEnd;
       }
   }
}

(もしかしたらこの辺り記述が足らないところがあるかもしれません。もしその時はお知らせください)
ビルドしたら、テストしてみます。以下のように「使う」を使用すると、インベントリからアイテムがなくなればOKです。

スクリーンショット 2020-05-12 22.42.21

アイテムを使ったらターンを経過させる

今度はアイテムを使ったらターンを経過させてみたいと思います。ですがこれはここまでのことができていたら、そこまで難しくありません。
久しぶりにSequenceManagerスクリプトを開きましょう。以下のように変更します。

// 以下のメソッドを変更
private void AllOperatedProc(bool isUseItem)
{
   if (isUseItem) inventoryAction.Proc();
   else playerAction.Proc();
   foreach (var enemyAction in operatedEnemies)
   {
       enemyAction.Proc();
   }
}

void Update()
{
   EAct iAct = inventoryAction.GetAction();
   if (iAct != EAct.KeyInput && iAct != EAct.ActEnd && iAct != EAct.TurnEnd)
   {
       inventoryAction.Proc();
       return;
   }
   EAct pAct = (iAct == EAct.ActEnd || iAct == EAct.TurnEnd) ? iAct : playerAction.GetAction();
   if (pAct == EAct.KeyInput || pAct == EAct.ActBegin || pAct == EAct.Act)
   {
       inventoryAction.Proc();
       if (iAct != EAct.KeyInput) return;
       playerAction.Proc();
       AllEnemyStopWalkingAnimation();
       return;
   }
   if (pAct == EAct.TurnEnd)
   {
       AllOperatedProc(iAct == EAct.TurnEnd);
       isEnemyDeterminedBehaviour = false;
       operatedEnemies.Clear();
       return;
   }
   if (pAct == EAct.ActEnd && !isEnemyDeterminedBehaviour)
   {
       AllEnemyDetermineBehaviour();
       return;
   }
   if (actEnemies.Count < 1 && moveEnemies.Count < 1 && (pAct == EAct.ActEnd || pAct == EAct.MoveEnd))
   {
       AllOperatedProc(iAct == EAct.ActEnd);
       return;
   }
   /*      省略      */
}

この図を見て下さい。

シーケンスインベントリ

アイテムを使用した時の流れはプレイヤーが行動した時と同じです。なのでアイテム使用後は擬似的にプレイヤーの行動状態をインベントリの行動状態とすること(pActにiActを代入している所)で、その後の処理をそのまま流用しています。またそれに伴い、AllOperatedProcメソッドもプレイヤーの更新関数を呼び出すか、インベントリの更新関数を呼び出すか選択できるようにしています。
という訳で、テストしてみましょう。アイテムを使用した直後に敵キャラクターが行動すればOKです。

アイテムターン経過

もし動かなかったら、それは筆者のミスです。お手数ですが、お知らせくださると大変助かります。

それでは今回はここまでということで。
次回はアイテムを置く処理を書いていきたいと思います。

この記事が気に入ったらサポートをしてみませんか?