見出し画像

【Unity】3Dローグライクゲームの作り方〜Step14-7〜

前回の記事はこちら
前回は倉庫インベントリのアイテムを表示しました。

アイテムを入れる処理

今回はアイテムを入れる処理からコードを書いていきたいと思います。
倉庫の空いているスロットを選択するとインベントリが表示され、アイテムを選択できるようにします。
まずはInventoryクラスを変更します。

// メソッドを追加
/**
* アイテムをインベントリの指定位置に加える
*/
public bool Insert(int idx, Item it)
{
   if (idx < itemNumMax)
   {   for (int i = items.Count; i <= idx; i++) items.Add(null);
       items[idx] = it;
       isSort = false;
       return true;
   }
   return false;
}

// メソッドを変更
public Item Get(int i)
{
   if (items.Count > i && i >= 0 && items[i] != null && items[i].id != EItem.NONE)
       return items[i];
   return null;
}

次にWareHouseDisplayクラスにメソッドを追加します。

/**
* 現在選択しているアイテムスロットのインデックスを返す
*/
public int GetSelectItemIndex() => selectItemIndex;

また、WareHouseActionクラスを変更します。

// パラメーターを追加
public InventoryActionInTown playerInventoryAction;

// メソッドを追加
/**
* インベントリにアイテムを挿入する
*/
public void InventoryInsertItem(Item it)
{
   itemInventory.Insert(display.GetSelectItemIndex(), it);
   display.Show();
}

// メソッドを変更
private void SelectItem()
{
   if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSEACTION))
   {
       selectItem = display.GetSelectItem();
       if (selectItem == null)
       {
           playerInventoryAction.OpenInventory(false, this);
       }
   }
}

最後にInventoryActionInTownクラスを変更して下さい。

// パラメーターを追加
private WareHouseAction isWareHouse;

//メソッドを変更
public void OpenInventory(bool isStone, WareHouseAction wareHouse = null)
{
   if (isStone)
   {
       display.inventory = stoneInventory;
       action = EAct.MoveBegin;
   }
   else
   {
       display.inventory = itemInventory;
       action = EAct.MoveBegin;
   }
   // 以下1行を追記
   this.wareHouse = wareHouse;
}

private void SelectItem()
{
   if (KeyConfig.GetKeyDown(KeyConfig.EType.INVENTORYACTION))
   {
       if (wareHouse == null)
       {
           string choiceOrder = "";
           selectItem = display.GetSelectItem();
           if (selectItem != null)
           {
               if (selectItem.isEquip) choiceOrder = "Remove";
               else
               {
                   choiceOrder = "Sell";
                   if ((int)selectItem.id < 1001) choiceOrder += ",Equip";
               }
               subMenu.SetChoices(choiceOrder);
               subMenu.Show();
           }
       }
       else
       {
           selectItem = display.GetSelectItem();
           if (selectItem != null) wareHouse.InventoryInsertItem(selectItem);
           action = EAct.MoveBegin;
           wareHouse = null;
           display.inventory.Remove(selectItem);
           selectItem = null;
       }
   }
}

実行してみます。空いているスロットを選択し、インベントリからアイテムを選びます。するとその位置にアイテムを入れられたはずです。

スクリーンショット 2020-11-09 19.17.43

アイテムを出す・交換する処理

次はアイテムを出す処理です。と言ってもここまでのことができていたら問題なくできると思います。
WareHouseActionクラスを変更して下さい。

private void SelectItem()
{
   if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSEACTION))
   {
       selectItem = display.GetSelectItem();
       playerInventoryAction.OpenInventory(false, this);
       action = EAct.Act;
   }
}

public Item InventoryInsertItem(Item it)
{
   int selectItemIndex = display.GetSelectItemIndex();
   itemInventory.Insert(selectItemIndex, it);
   display.Show();
   Item item = selectItem;
   return item;
}

private void Act()
{
   selectItem = null;
   action = EAct.ActBegin;
}​

InventoryActionInTownクラスも変更します。

private void SelectItem()
{
   if (KeyConfig.GetKeyDown(KeyConfig.EType.INVENTORYACTION))
   {
       if (wareHouse == null)
       {
           /*   省略   */
       }
       else
       {
           selectItem = display.GetSelectItem();
           Item item = wareHouse.InventoryInsertItem(selectItem);
           action = EAct.MoveBegin;
           wareHouse = null;
           display.inventory.Remove(selectItem);
           if (item != null) display.inventory.Add(item);
           selectItem = null;
       }
   }
}

実行してみます。スロットを選択してからインベントリで空の部分を選ぶとそのままアイテムがインベントリに入るはずです。また、アイテムが入っている箇所を選択するとその位置のアイテムと交換できます。

スクリーンショット 2020-11-09 20.03.44

装備中のアイテムは入れられないようにする

ですが問題があります。このままだと装備中のアイテムまで倉庫に入れることができてしまうことです。
この問題の解決方法は2種類あります。

・装備を外してから倉庫に入れる
・装備中のアイテムはそもそも入れられないようにする

今回は後者を採用しようと思います。
という訳でアイテムが装備中でなければ(=isEquipがfalse)操作できるようにします。InventoryActionInTownクラスを変更して下さい。

private void SelectItem()
{
   if (KeyConfig.GetKeyDown(KeyConfig.EType.INVENTORYACTION))
   {
       if (wareHouse == null)
       {
           /*   省略   */
       }
       else
       {
           selectItem = display.GetSelectItem();
           if (selectItem == null || !selectItem.isEquip)
           {
               Item item = wareHouse.InventoryInsertItem(selectItem);
               display.inventory.Remove(selectItem);
               if (item != null) display.inventory.Add(item);
           }
           action = EAct.MoveBegin;
           wareHouse = null;
           selectItem = null;
       }
   }
}

ページ表示

そろそろ現在のページ数も更新しましょう。WareHouseActionクラスを以下のように変更して下さい。

using UnityEngine.UI;

public Text pageText;

private void ActBegin()
{
   if (selectItem == null)
   {
       bool isCursorMoving = !MoveSelectItem();
       if (isCursorMoving) return;
       KeyInput(false);
       SelectItem();
   }
   else
   {
       UnSelectItem();
   }
   pageText.text = (display.GetPageNum() + 1) + "/" + display.GetPageNumMax();
}

実行してみます。

スクリーンショット 2020-11-09 21.13.07

ページ数が更新されました。

おまけ:倉庫ウィンドウのカーソルがおかしい

倉庫ウィンドウにてカーソルを下に入力すると最後の要素が選べません。
これを直すためにWareHouseDisplayクラスを変更します。

public bool MoveSelect(EDir d)
{
   int viewSelectItemIndex = view.GetSelectItemIndex();
   content.GetComponentsInChildren<ScrollItem>()[viewSelectItemIndex].SetSelected(false, true);
   bool isMove = true;
   switch (d)
   {
       case EDir.Left:
           if (viewSelectItemIndex + leadShowItemIndex == 0)
           {
               if (inventory.itemNumMax % maxShowItemNum == 0)
                   leadShowItemIndex = inventory.itemNumMax - maxShowItemNum;
               else
                   leadShowItemIndex = inventory.itemNumMax - inventory.itemNumMax % maxShowItemNum;
           }
           else if (viewSelectItemIndex == 0)
               leadShowItemIndex -= maxShowItemNum;
           break;
       case EDir.Right:
           if (viewSelectItemIndex + leadShowItemIndex == inventory.itemNumMax - 1)
           {
               leadShowItemIndex = 0;
               while (view.GetSelectItemIndex() > 0) view.MoveSelect(d);
               isMove = false;
           }
           else if (viewSelectItemIndex == maxShowItemNum - 1)
           {
               leadShowItemIndex += maxShowItemNum;
               while (view.GetSelectItemIndex() > 0) view.MoveSelect(d);
               isMove = false;
           }
           break;
       case EDir.Up:
           if (viewSelectItemIndex + leadShowItemIndex < view.column)
           {
               if (inventory.itemNumMax % maxShowItemNum == 0)
                   leadShowItemIndex = inventory.itemNumMax - maxShowItemNum;
               else
                   leadShowItemIndex = inventory.itemNumMax - inventory.itemNumMax % maxShowItemNum;
               Show();
           }
           else if (viewSelectItemIndex < view.column)
               leadShowItemIndex -= maxShowItemNum;
           break;
       case EDir.Down:
           if ((GetPageNum() == GetPageNumMax() - 1) &&
               (viewSelectItemIndex >= ((inventory.itemNumMax - leadShowItemIndex) / view.column) * view.column))
           {
               leadShowItemIndex = 0;
               Show();
               viewSelectItemIndex %= view.column;
               while (view.GetSelectItemIndex() != viewSelectItemIndex)
                   view.MoveSelect(EDir.Left);
               content.GetComponentsInChildren<ScrollItem>()[viewSelectItemIndex].SetSelected(true);
               isMove = false;
           }
           else if (viewSelectItemIndex > maxShowItemNum - view.column - 1)
           {
               leadShowItemIndex = maxShowItemNum * ((GetPageNum() + 1) % GetPageNumMax());
           }
           break;
   }
   Show();
   if (isMove) view.MoveSelect(d);
   Show();
   selectItemIndex = leadShowItemIndex + view.GetSelectItemIndex();
   return true;
}

というところで今回はここまでです。次回は倉庫内のアイテムをソートできるようにします。

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