<前文>
Vtuberについて2
しかしvtuberというのは凄い発明ですね。幾ら見ても飽きないです。びっくりしたのはボイスチェンジャーを使用すればおじさんですら美少女vtuberに成れる事です。個人的にはGoogleの検索エンジンに匹敵する発明だと思いました。MMDを初めて見た時も思いましたが、日本文化は他に類を見ない発想とそれを実現する科学技術を持つ稀有なもののようです。
こういう事は誇っていいと思います。いつも日本凄いと言っているネトウヨと言われる人達は、こういう事は決して褒めないですね。何でしょう。日本文化が他に類を見ない発想とそれを実現する科学技術を持つ稀有な文化だと嫌なんでしょうか?
しかし問題もある事も分かりました。見終わっても何にも学んだ事がないです。しかも時間を大量にとる為、後で別の動画を見る事も出来ません。先々週、あんなに心配していたEpic games とアップル社の裁判も現在どうなっているのか全く分かりません。大学教授とかがvtuberになって講義をストリームしてくれると遊びながら学習出来て更に良いですね。
遊びながら学習と言えば、私が作成している英語の発音が学べるゲームですが、LとRの音を持つminimal pairな単語を大量に追加しました。その音でテストしたらLやRの音が一種類でない気がしてきました。Dark LとLight Lについては私も知っていますが、それ以上にLの音があるような気がしています。そこで思い出したのですが、アメリカ人がLの発音する時、実際はThみたく舌を噛んでいる人が一定数いた気がします。Rの発音でも下の先を丸めるRと舌の奥をスプーンみたく丸めて発音するRの音は違う気がします。日本人でLとRの発音が出来ている人でもLとRを聞いたときに区別が付かないのは、単純にLとRに沢山の音があってその全部の音を知らないからかもしれません。
私は音声学を勉強したわけではないので、そういう説があるのかは知りません。しかし例え無くても、日本人がLとRの区別が付かないのは単純にLとRに沢山の音があってその全部の音を知らないから説は仮説としてはあり得る気がしています。
それでは今週の勉強を始めます。
<本文>
先週からゲームのアート的な部分も制作し始めました。その結果プログラミングの勉強がおろそかになりがちなので、今週からプログラミングパートとデザインパートを分けて勉強する事にします。
Programming Part
今週はCh4_3 をGithubにでも上げようと思っていたのですが先週から考えた結果、あまりメリットがないと結論が出ました。今までも使用しなくても問題なくやってこれましたし、所詮一人で作成していますから。のでGithubにこのプロジェクトを上げるのは止めます。でなにをするかと言うと、
戦闘システムの「道具」と「逃げる」を選択した場合を作成していなかったのでそれを作成します。
デザイン編
今週は先週作成したショップをマップ内に配置して道具屋と武器屋を作成します。
1. Programming Parts
1.1 逃げるボタンの実装
まず、逃げるボタンを選択したらCombatUIウィジェットの変数CombatSelectedのenumをRunにセットします。
あれ、「逃げる」って選択をとる為には、BPの変更だけでなくUE4C++からの変更や戦闘エンジンそのものの変更も必要ですね。
戦闘が終わった時は二つの状態しか設定していませんでした。負けた時と買った時です。これに逃げた時を追加する必要がありますね。
CombatEngineのCombatEngine.hに設定されているenumの CombatPhaseにCPHASE_MakeOffを追加しました。
これで逃げるボタンを選択したら、RPGGameModeBaseクラスにあるCombatEngineの変数内の変数PhaseがCPHASE_MakeOffに変更されるようにすればいいはずです。
そのためには、まずCombatEngineクラスのTick()関数にCase CombatPhase::CPHASE_MakeOffを追加します。
因みに、CPHASE_VictoryとCPHASE_GameOverは
こんな感じでPhaseを変更しています。
あれ?
Phase変数はPublicに指定されているのに、
SetPhase() 関数がprotectedに指定されている。
支離滅裂過ぎる。
いくらなんでも私はこんなコードは書きません。教科書を見たらやっぱり
教科書にそう書かれていました。
うん。あんまり教科書を信用するのも善し悪しですね。
今回はこのままにして置きますが、CombatEngine3を自作する時は全部書き直します。
変数、PhaseをCPHASE_MakeOffに変更する方法ですが、
- CombatEngineクラス内に、Phase変数の値をCPHASE_MakeOff に変更するPublicな関数を作成。
- RPGGameModeBaseクラスにその関数を呼ぶBPから実行可能な関数を作成。
- CombatUIウィジェットで逃げるボタンを選択した時にその関数を呼び出せるように実装。
でやってみます。
CombatEngine.hにRPGGameModeクラスから呼び出せる関数、SetPhaseToMakeOff()関数を宣言しました。
更にCombatEngine.cppにSetPhaseToMakeOff()関数を実装します。
今度は、RPGGameModeBaseクラスからこの関数を呼ぶ関数、SetCombatEnginePhaseMakeOff()を作成します。
まず、UFUNCTIONがBlueprintCallableなのでBPからこの関数は呼べるはずです。
BPとUE4C++そして生のC++の関係は民間、政府、外国の関係と思うと分かり易いと前に書きましたが、民間企業が自国の政府に要請してその政府から更に外国の政府に要請の手順を踏む事で外国政府に要件を聞いてもらうように、BP→UE4C++(RPGGameModeBaseクラス)→生のC++(CombatEngine)となっています。
ビルドも成功しました。
本当にBPからPhase変数の値をCPHASE_MakeOffに変更出来ているのか確認するために以下のコードをRPGGameModeBaseクラスのTick()関数に追加します。
テストします。
逃げるボタンを選択したらRPGGameModeBaseクラスのSetCombatEnginePhaseMakeOff()関数を呼び出すように実装しました。
Phase変数の値はCPHASE_MakeOffに変更されているみたいですね。
今度はこの中を正しく実装していきます。
まずisNotPrintyet変数ですがこの中のコードを一回だけ実行するための変数です。一回実行したらFalseにセットします。それだけです。
この関数内で実行されるReportFightIsOver()関数が全てを管理しています。
ReportFightIsOver()関数はBlueprintImplementableEventなので実装はBPで行います。
まず最初の部分ですが
戦闘に勝った場合と負けた場合の2つに分かれています。ここにescapeを追加する必要があります。
以下に勝った場合を示します。
表示するセリフが示されています。
逃げた場合のセリフをここに作成する必要があります。
以下の部分は読みましたボタンを表示しているのとそのボタンがクリックされたのを確認しているだけなので変更は必要ないです。
これが読みましたボタンです。
その後の部分ですが、アニメーションを流しています。戦闘に勝った時は勝利のポーズ、負けた時は敗北のアニメーションを流しています。
その後で、HadReadFightIsOver()関数を呼び出しています。
以下にRPGGameModeBase.hで宣言されているHadReadFightIsOver()関数を示します。
実装部はこんだけです。
FightIsOverIsRead変数がtrueになるとTick()関数内の以下のコードが実行されます。
成程、大体分かりました。
こんな感じに直しました。
まず新たなEnum, CombatOverStateを作成しました。以下に示した通り、VictoryとGameOverだけでなくEscapeがあります。
このEnumを使用してReportFightIsOver()関数を以下のように変更しました。
BPに移ってReportFightIsOver()関数の実装になります。Victory変数をBooleanタイプからCombatOverStateタイプに変更しました。
当然、分岐もbranchからSwitchに変更しています。
逃げた時のコメントを追加しました。
逃走した時のアニメーションは要らないのでアニメーションパートはスキップします。
これで出来たはずです。
テストします。
逃げるを選択するとコメント欄に“KUMO”は逃走しました。と表示されました。
そして元の場所に戻りました。出来ていますね。
1.2 道具ボタンの実装
今度は道具ボタンの実装をしていきます。最初はこっちの方が難しいと思ったのですがどうでしょうか?BPだけで実装出来そうな気もしています。
取りあえず道具ボタンを押したら、持っている道具が表示されるように実装してみました。
こんな感じで表示されています。
Itemウィジェットをそのまま使用したのですが字が切れてしまってますね。
カーソルを道具ボタンの上に置くと、
その道具の詳細が表示されます。これはカッコイイです。
よし決めました。ここでItemウィジェットを使用するのは止めます。新しくCombat_Itemウィジェットを作ってそれを使用します。
作りました。ItemウィジェットをDuplicateした物に文字の大きさを変えただけです。
道具の詳細を表示するウィジェットも新しく作りました。
良い感じです。
今度はアイテムボタンがクリックされた場合の実装をします。
まずクリックされたアイテムが何なのかを保持するためにCombatUIウィジェット内に変数を一個作成します。
ボタンをクリックした時にこの変数にクリックされたボタンのアイテム名を保持出来るように
CombatItemにCombatUIをパスしておきます。
更にcustom event, ItemButtonClickedを作成して
それをCombatItemボタンが押された時に呼び出します。
取りあえずここでテストします。
回復薬をクリックすると左上に回復薬と表示されます。ここまでは正常に動いてるようです。
今度は、アイテムをクリックしたら対象の人が表示されるようにします。といっても対象はユーザーが操作するキャラかモンスターの2種類しかいませんが。
そう言えば、魔法を選択した場合、どうやって実装しているのかチェックし忘れていました。そっちを先に見ます。
魔法を選択すると使用出来る魔法がScroll boxであるChoose内に表示されます。そしてその中から魔法を選択すると
魔法の対象となるモンスター名が表示されます。
魔法を表示するウィジェットは、
で結構しっかり作り込まれていました。
これは、Combat_Itemを作成する前に見るべきでしたね。ちょっと遅きに失してしまいましたが、今から見ていきます。
まず、TargetとTargetUIがあります。TargetはGameCharacterタイプの変数で攻撃対象のモンスターを保持しています。TargetUIはCombatUIタイプの変数でこのMagicUIを保持しているCombatUIのインスタンスを保持しています。
TargetとTargetUIの値はMagicウィジェット作成時にparameterとしてパスされています。TargteUIはselfをパスすればいいだけですが、Targetはどうやって収得しているか分かりません。
分かりました。この関数が取ってきていました。
この関数、UE4C++のCombatUIWidgetクラスで作成していました。
うーん。成程、最適化からは程遠いですが、一応敵のGamecharacterクラスを返していますね。
更にMagicボタンがクリックされた場合を見て行きます。
CombatUIウィジェットのTarget内のChildrenを全部消しています。魔法ボタンをクリックした時に同じ事を既にやってなかったかなと思って見直して見ると
やってなかったです。
ただし、さっき作成したItemボタンをクリックした時は、
思いっきりやってます。どっちがベターな方法なんでしょうか?後で考えます。
Magicボタンに戻りますが、
その対象のモンスターが生きているのか確認していますね。これは1対1のバトルに変更した今では要らないはずですが、あっても問題がある訳でもないので残しているのでしょうね。
その後で、今度はTargetに入るボタン、つまり対象となるモンスターを表示するウィジェットを作成しています。AttackTargetOptionウィジェットは後でみます。
最後にコメントを表示していますね。これは大切でした。
AttackTargetOptionウィジェットも次いでに見てみましょう。
ボタンを表示するためのウィジェットなのですが、CanvasPanelを使用していますね。
コメントを最後に表示する処以外は普通ですね。
大体分かりました。魔法の時のやり方が楽な気がしてきました。
ただ、Targetは結局、RPGGameModeBaseクラスにある変数、EnemyMonsterとRPGGameInstanceクラスにあるMyYourHero変数なので、parameterとしてパスしなくてWidget内でアクセス出来るのでどうしようかなと思っています。
よし決めました。基本は、魔法を選択した時のやり方で多少マイナーチェンジをします。
こんな感じに作成しました。
まずCombatUIウィジェットで道具が選択された時です。
そして、表示されたアイテムの一つがクリックされた時です。
ここで開かれるTargetCharacterウィジェットは、AttackTargetOptionウィジェットを参考にして作成しました。
TargetCharacterウィジェットから作成された対象となるキャラを選択した時は、
こうなります。
まだセリフなどは追加していませんが、これで一応動くはずです。
テストします。
回復薬を選択します。
使用する対象が表示されました。KUMOを選択します。
あれ、動かなくなってしまいました。
調べたらこの関数を呼ぶ必要があるみたいです。
これは、CombatEngineを見直す必要がありますね。
今週はここまでにして残りは来週作成します。
2. Design Parts
2.1 道具屋の配置と作成
先週作成した店を配置してみます。
外から見た感じです。結構いい雰囲気が出ていますね。
店の後ろに回って見ました。雰囲気は良いですが、何か全体的に暗いですね。
店の中に入って見ます。やはりちょっと暗すぎますね。
横から見た風景です。これは暗すぎませんね。
Eを押せば道具屋のUIが始まります。
まあ、最初の段階としては良い感じです。これで道具屋と武器屋の区別が付くようにします。
色々考えたんですがこれが一番分かり易いです。
これでいきます。
武器屋も作成しました。
中身です。
2.2 これからの課題
一応、これで道具屋と武器屋が出来ました。この後、村や町そして城を作成しようと思います。それぞれ別なlevelに作成する予定です。以下の事を考える必要があると思っています。
- 街全体のサイズ。ランドスケープで制作する場合の設定はどうすればいいのか。ランドスケープを使用しない場合は、町は平らになる。無料で配布されているマップを使用した場合はどうなのか?
- 別なlevelに移行して戻った場合、前のlevelで採取したアイテムやモンスターが再生されて配置される。一度取ったら再生されないようにするにはどうしたら良いか?
- Weapon ShopやItem Shopを日本語表示したい。
2.3 無料のマップの確認
Medieval Kingdomの付属のマップを開いて見ていたらPCが凄い音を立てました。正直こんなvideo cardに負担をかけるマップは使用したくないです。自分で作成する事にします。
ただもう時間が無くなってしまったので残りは来週します。
3. 感想とまとめ
今週はここまです。