<前文>
<本文>
<目的>
7章、ゴールド、アイテム、そして店 (Gold, Items, and a Shop)を勉強します。
- NPCを店主として使用します。
- ユーザーが買えるアイテムを表示します。
- ユーザーはアイテムを買うための通貨が必要です。
- 以下のトピックをこの章ではカバーします。
とありました。どんどんやって行きましょう。
<方法と結果>
<Step.0>
まず、サンプルコードのChapter7を解凍します。
普通に解凍出来ました。先週、間違ってビデオカードのドライバーを消してしまい、危うくPCが壊れるくらいCPUの温度が上昇した事があったのですが、UE4には何の影響もなさそうですね。
前回と同じように、Ch2を使用してやっていきます。
<Step.1>
ゴールドのインスタンスをゲットする事とセットする事(Setting and getting gold instances)
- まずショッピングのインターフェイスを作成します。ショップボタンを通して、店内でアイテムを買うための通貨を引き出せるようにします。
- ゴールドは戦闘の終わりに敵が落とすようにします。ので敵のデータのプレイヤーが得る事の出来るゴールドのデータが必要です。
- 4章, Pause Menu Frameworkでゴールドのプレイスホルダーを持つポーズメニューを作成しました。のでゴールドをこのポーズメニューに追加しましょう。
はい。
ゴールドのプロパティをFEnemyInfo.hに追加します。
教科書に書かれている通りに追加します。
しました。
- 次に我々のゲームキャラクターのゴールドプロパティ(Gold property)を作成します。
- hにFEnemyInfo.hと同じように作成します。
はい。追加しました。
<Step.2>
GameCharacter.cpp 内でEnemyInfoでセットした値と同じ値のGoldの返し値をセットします。
まず、教科書の説明通りにCreateGameCharacter(FEnemyInfo* enemyInfo…関数内でGoldに値をアサイン(assign)します。
<Step.3>
- 何時ゴールドを追加するか選ばなけらばなりません。
- コンバットからにします。
- hを開き、バトルで獲得した全てのゴールドを保持するためのgold変数を作成します。
作成しました。
<Step.4>
- 次のステップはエンジンにいつゴールドをプレイヤーに渡すのかをエンジンに告げる事です。
- cppを開き、勝利をチェックするために3章Exploration and Combatで作成したループまでスクロールします。
- そこにGold を宣言します。
- そして0をセットします。
はい。変数Goldを追加し0で初期化しました。
<Step.5>
- もしプレイヤーが勝利しないで戦闘をする必要がある場合戦闘で得られるゴールドは0にセットされます。
- 次に、全ての殺した敵からゴールドを集めます。のでループ内でそれぞれの敵のゴールドをGold変数に足していきます。
となりました。
<Step.6>
- ループが終了した後に、敵のパーティが全滅したかどうかをチェックする必要があります。
- もし敵のパーティが全滅した場合は戦闘に勝利したので、ループで足したゴールドを獲得します。
- 獲得したゴールドは単純にGoldTotalに追加されます。
追加しました。
<Step.7>
- 次にする事はゴールドをゲームデータに追加する事です。
- もっと詳しく言えばゴールドをhに追加する事です。
しました。
<Step.8>
- 次に、勝利の条件とゲームオーバーの論理を作成したcppファイルに行ってGameGoldのインスタンスを作成します。
- 勝利の条件内にgameInstanceを呼ぶURPGGInstanceへのポインターを作成します。
- そしてそれをGetGameInstanceへキャストしてイコールします。
一寸、英文が何を言いたいのか分からない部分がありましたが、コードを見ながらやって行けば大丈夫でしょう。
これを作成する事を説明していたみたいですね。
説明通りにRPGGameMode.cppを開いて戦闘の勝利の箇所に上記のコードを追加します。
しました。
<Step.9>
このGameInstanceを使用して戦闘から得たトータルゴールドをGameGoldに追加します。
しました。
<Step.10>
この時点でコンパイルするか確認して下さい。
はい。
成功しました。
<Step.11>
- 敵のデータテーブルからそれぞれの敵のキャラクターのゴールドの価値を調節出来るようになりました。
- 敵のデータテーブルを見るとGoldの列がみれるはずです。
- Goldの列に好きな値を追加してデータテーブルをセーブしてください。
データテーブルのEnemiesを開いて見ると以下に示すように確かにGoldが追加されています。Goldの値を10に変更しセーブしました。(ついでにMHPの値も2に変更しました。)
<Step.12>
- もしプレイヤーが戦闘で買ったら手に入る金に変換されたリアルな価値が敵の情報に付いています。
- 次にポーズメニューそのGoldを表示する必要があります。
ポーズメニューのGoldにGameInstanceのGameGoldが表示されるように以下に示すようにブループリントを組みました。
以下に示す教科書の参考と全く同じです。問題ないですね。
<Step.13>
アイテムのデータ(Item data)
- お店を作成する前にもう一つ作成しなければならない物があります。アイテムです。
- データテーブルを使用してアイテムの状態とインベントリーを管理するのが一番楽です。
- なので、まず、前に作成したCharacterInfoの構造体に似た、新しいC++のFTableRowBaseの構造体を作成します。
- hとItemData.cppと呼びます。
まず、FTableRowBase 構造体を親に持つItemsData.hとItemData.cppをSource | RPG | Dataのフォルダー内に、CharacterInfoの構造体を作成した時と同じように作成してください。とあります。
もう作り方忘れちゃったよ。と思いましたが、良く考えたら自分のブログに詳しいCharacterInfoの構造体の作成手順が残っているはずです。2019-05-19のブログにCharacterInfoの構造体の作成方法が書かれていました。
読んだら、Dataフォルダーは作成しないでCharacterInfoの構造体の構造体を作成していますね。ちょっと教科書のやり方とは違いますが2019-05-19のブログのやり方で作成します。
まず、C++の親にObjectを選択します。
名前をItemsDataにします。PathはDataフォルダーを作成していないので、そのままです。
以下に示したようにItemsData.hが出来ました。
教科書の説明に基づいて以下に示すように変数を宣言しました。
ビルドしてみます。
あっけなく成功してたと思ったらクラッシュしました。
Ch2プロジェクトをもう一度開いてビルドしましたが
問題ないみたいです。今度はクラッシュもしません。2019-05-19のブログにも最初にCharacterInfoを作成した時にクラッシュしたと書かれていました。
2019-05-19のブログではVSをリフレッシュしたと書いていたので、一応VSをリフレッシュしておきます。
自画自賛になりますが、2019-05-19のブログのおかげでItemsData.hを簡単に作成する事が出来ました。やっぱりブログに記録しておくことは大事ですね。
<Step.14>
ItemsDataから店のためのデータテーブルを作成します。
Items_Shopと名付けます。
アイテムとしてpotionを作成します。
<Step.15>
店のスクリーンのフレームワーク(The shop screen framework)
店のスクリーンのフレームワークとは一体何でしょうかね。全く分からないですね。まず教科書を読んでみます。
- 前章でダイアログボックスを店主のために作成しました。ダイアログボックスの一つにShopボタンを作成しました。
- そのボタンをクリックするとショップメニューが開きます。
- まず、このショップメニューを作成しましょう。
どうやらショップメニューの事のようですね。それではやって行きます。
Content | Blueprints | UI | NPCフォルダーにShopと言う名前の新しいウィジェットブループリントを作成します。
出来ましたが、位置は滅茶苦茶ですね。ウーン。何か特別なやり方があるのでしょうか。今回はウィジェットの数が少ないので一個ずつ手動で直していきます。
直しました。
<Step.17>
次にPause_InventoryウィジェットブループリントからScrollBox_InventoryとTitle_Inventoryをコピーペイストします。
ShopウィジェットブループリントにPause_InventoryウィジェットブループリントのScrollBox_InventoryとTitle_Inventoryを追加しました。
- InventoryをShopに変更します。
<Step.18>
しました。
テストします。
Shopをクリックします。
Shopブループリントが開きました。
開きましたがExitボタンを押しても閉じません。
取りあえずこの問題は無視して教科書の指示に従って進めます。最後までこのExitボタンを直さない場合はその時に自分で直します。
<Step.19>
Gold数を画面に表示出来る様にします。
しました。
今度はGoldの値が表示されています。
<Step.20>
次にButton_Exitの機能を追加します。
ここでExitボタンの機能を追加するのですね。
これだけで良かったのでしょうか?マウスのカーソルとかの後処理なんかいらないのでしょうか?
<Step.21>
アイテムボタンのフレームワーク(The item button framework)
今度はアイテムボタンのウィジェットを作成するのでしょうか?
- アイテムをこのShopにリンクする前に、アイテムを店内に配置するためのフレームワークを作成する必要があります。
- まず、店主が売っているそれぞれのアイテムのためのボタンを作成したいです。
- ただしNPCらがスケールの違うアイテムを持つ事が出来るようなスケーラブルなインターフェイスを作成するためには、そのアイテムのテキスト/説明のためのデファルトな値を持つ一個のボタンを持つスクロールボックスのフレームワークを作成するほうが賢いです。
- そうする事で、店主が持つ沢山のアイテムのためのボタンを動的に描き、更にそれぞれのボタンのテキストを動的に描く事が出来ます。
うん。大体そうみたいですね。
まずItemと言う名前のウィジェットブループリントを作成します。
作成しました。
その後の指示に従ってItem内にボタンを作成します。
Canvasを削除してボタンを追加しました。
ボタン内のテキストにテキストタイプの変数であるItemをバインドしました。
<Step.22>
アイテムのデータのリンク(Linking the item data)
- アイテムボタンフレームワークを使用してアイテムデータと店をリンクします。
- そのために、アイテムボタンフレームワークを使用してItem_Shopのデータテーブル内のそれぞれのアイテムを表示するための機能を追加します。
もう教科書に書かれたままに作成しました。
ちょっと良く分からない箇所もありますが、多分大丈夫でしょう。(これだとアイテムの名前しかパスしていないように思えます。)
テストしてみます。
綺麗にPositionが表示されました。
これだけでは、勿体ないのでetherを作成して試してみます。
綺麗に表示されましたね。
<考察>
UEC++とは関係ないですが、ウィジェットブループリントから他のウィジェットブループリントを呼ぶ技術はカッコイイのでその辺を考察してみたいです。
まず、AddChildノードを使用しています。これがウィジェットブループリントから他のウィジェットブループリントを呼ぶためのノードですね。Targetに親ウィジェットブループリント内の子ウィジェットブループリントを表示したいウィジェット(この場合ScrollBox_Inventory)が接続されています。Contentの方は、子ウィジェットブループリントが接続されています。子ウィジェットブループリントのインスタンスはCreateWidgetノードで作成されています。
どうやってボタンのテキストに値をパスしているのか?と思ったら、以下に示すように予めItemと言う名の変数を作成していました。
<感想など>
もう簡単な章しか残っていないと思っていたら7章は結構ボリュームがありました。勉強のし甲斐がありました。