気づけばツール漬け

3D,2Dのツールを色々使ってみた記録を書いていきたいです。

「花咲かGrayちゃん」制作メモ 背景編

f:id:mi-zmix:20200409155309p:plain

第13回UE4ぷちコン応募作「花咲かGrayちゃん」制作メモ今回は背景についてです。

前回の記事はこちらです。

mi-zmix.hatenablog.com

ゲームはこちらからダウンロードできます。

drive.google.com


 

プレイエリア

背景は強制スクロールにしました。カメラのX位置は動かさず、背景(タイルマップ)の方が動いています。

f:id:mi-zmix:20200409155425p:plain

だいたい1画面分をコリジョンで囲ってプレイエリアとしました。左端と下にオーバーラップするとゲームオーバーです。
左側は、キャラ1人分くらいの余裕があります(警告を表示するためのコリジョンの範囲)。画面左端に完全に隠れても、しばらく大丈夫なのでギリギリを狙ってみてください。
画面の右端になる部分にはプレイヤーが先に進んでいかないように、ブロックのコリジョンを置いています。
空にはコリジョンを設定していません。マップの上に乗って画面外に出られる場所がいくつかあるのですが、上にのっても特にメリットはないのでそのままにしました。

タイルマップBP

タイルマップの作り方などは省略します。
タイルマップは、それをそのままアクターBPにして親BPとしました。それのチャイルドBPとしてマップのバリエーションを作成しました。
親BPには、木をスポーンする場所と、柵をスポーンする場所のプレイスフォルダを一個ずつ置きました。

f:id:mi-zmix:20200409160027p:plain

チャイルドBPの方で、木と柵のプレイスフォルダーを必要な数だけデュプリケートして作り適当な場所に配置しました。
親BPでアローコンポーネントの子として配置してあるので、チャイルド側でもその子として複製して増やしていきます。

f:id:mi-zmix:20200409160143p:plain

複製した各プレイスフォルダを、親になってるアローコンポーネントからGet Children Componentで全部取得して、配列に入れてシャッフルします。そこから設定した個数分だけスポーンするようにしました。0個に設定した場合はスポーンしません。

f:id:mi-zmix:20200409160516p:plain

だいたい、1マップあたりに木を8箇所と柵を4箇所程度配置して、その中から各マップで、4~6本の木と1~2個の柵が出るようにしました。
タイルマップのバリエーションは全部で11個作りました。

タイルマップは1グリッドを16ピクセルにしました。
2レイヤー構造にして、前に来る方にコリジョンを設定しています。後ろのレイヤーは、ぶつからない絵として地面に生えている草とか道路標識を置きました。

f:id:mi-zmix:20200409161103p:plain

タイルマップをつなげる仕組み

タイルマップをつぎつぎと消してはつないでいくという仕組みを作りました。今回の、「自分としては頑張ったポイント」なのですが、あとから考えてみれば、こんな工夫もいらなかったのかもと思ってます。
ゴールあり(終わりが見えている)タイプにしたので、最初から全ステージを並べてしまえば済むことでした。とはいえ最初はエンドレス(無限Run)で考えていたので、次々とスポーンしては消していく仕組みにしなくては! と思ってとりくんだのです。

変化していく地形を実現するため、複数のパターンのタイルマップBPをランダムに選んでつなぐという方法にしました。さらに、マップの難易度を想定して、前半と後半で選ばれるタイルマップの内容を変えました。
マップをつなぐ流れは、TileScroller(Spawnerの方がよかったかも)というBPを作って、それで制御しました。

まずスタート直後に1個、スタート用のタイルマップの右端にスポーンします。スタート時のタイルマップは必ず固定にしました。タイルマップのピボットは、左上タイル1個の中心という半端な位置にあるので、その部分にターゲットポイントを置いてTransformを取りました。

f:id:mi-zmix:20200409161528p:plain

レベルの左端にコリジョン(EndPointという名前)を、設定しました。タイルマップが左端においてあるコリジョンにオーバラップしたときに消すようにしました。同時に、次のタイルをスポーンさせるイベントディスパッチャをコールします。
消すためのコリジョンがあるエンドポイントのBPは、あらかじめ変数にいれて参照しています。
あと、スポーンしたマップの数が必要なので、ゲームモードから現在スポーン済みの数を取得しています。(新しいマップをスポーンした時に、GameModeの変数へ+1しています)

f:id:mi-zmix:20200409161848p:plain

タイルをスポーンする場所は、前回スポーンしたタイルマップの右端の位置にしました。タイルマップの右端にアローを置いて(AttachPoint)、ここのWorldTransformを取得するようにしました。

f:id:mi-zmix:20200409162213p:plain
この場所はゲーム中に左に向かってどんどん移動してしまうので、つかまえておくための対策として、スポーン直後のタイルマップを変数に入れました。イベントディスパッチャにバインドしてあるイベントの流れで、現在移動中(変数に入れておいた)のタイル右端のワールドトランスフォームを取得して、そこにスポーンさせます。

f:id:mi-zmix:20200409163416p:plainこのとき、1ドット(1ユニット)分の隙間が空いてしまったため、X軸のオフセットをしています。時々ピッタリ合っている場合もあったのですが、隙間があくよりも微妙に重なっている方が不自然ではないので1ドット分オフセットしました。
追加した遠景のタイルマップも同じ仕組みを使いました。スクロールスピードの基準値は同じにして、0.25倍しています。

タイルのバリエーションは、スポーン用の自作関数(SpawnNewTileMap)の中で変えるようにしました。

f:id:mi-zmix:20200409163908p:plain

f:id:mi-zmix:20200409164612p:plain
前半用のタイルマップ配列と、後半用のタイルマップ配列を設定しておいて、BeginPlayでシャッフルしておきます。あとは、配列の中を順番に取り出していきます。MapDifficultySelectマクロの中でやってます。

f:id:mi-zmix:20200409164143p:plain
SetMapDifficultyマクロの中で、難易度分けをしました。
前半用に設定した数分スポーンしたら、後半の配列に切り替えました。後半の設定数分スポーンしたらゴール用のタイルマップをスポーンして終わりです。

f:id:mi-zmix:20200409164356p:plain
いくつスポーンするかの数値を変えるだけで、ゲーム全体の長さを調整できるので、これはこれで作ってよかったかなと思います。

木と柵

木は最初、物理でマップに置くだけにしようと思っていたのですが、すべり落ちたり荒ぶったりして、だめでした。

動かないようにしてしまうと、スクロールにおいていかれるので、タイルマップと同じ速度で動くようにして、動いて見えないアクターにしました。
キャラクターBPならスクロールに乗ってくれるので、それを使うのも良かったのかもしれませんが、そこそこの数が出ますし、なんか処理的にもったいない感じがしたので避けました。
柵も同じ方法をとりました。
各タイルマップBPもこのTickの流れと全く同じ仕組みで動かしました。スタートやリザルトに変わる時、スクロールを始めたり止めたりするのにGameModeからのイベントディスパッチャを使いました。全部一度に受け取れるので便利です。

f:id:mi-zmix:20200409165218p:plain

Scroll Move関数の中はこんな感じです。

f:id:mi-zmix:20200409165533p:plain

スクロールスピードの基準値は、GameModeだけで設定して、同じ速度で動くやつらは全員その値を取得しています。

木と柵も、マップと同じように左端にあるマップを消すためのコリジョンにオーバーラップしたら消すようにしました。そこはかなり遠くにあるので、木が画面左端に消えても、灰が届けば花は咲きます。見えませんが。

木は灰を受けたときに、チャイルドアクターとして花びらのアクターをAddするようにしました。

f:id:mi-zmix:20200409171724p:plain
AddFlowerActor関数の中。

f:id:mi-zmix:20200409171904p:plain

灰を受けるたびにAllFlowersStepUpマクロの中で、Addしてる全チャイルドアクターに、インターフェイスで花の段階をすすめる通知をしました。

f:id:mi-zmix:20200409172224p:plain
5段階目で満開にするので、オーバーラップの反応を止めて、チャイルドアクターで花をばらまくようにしました。

f:id:mi-zmix:20200409172444p:plain

ぱ~~~っとばらまいたあとで、最初にアドしていた花びらのアクターを消してます。時々数が減って見えるのはこのせいです。これは花のBP側で処理しました。

f:id:mi-zmix:20200409172648p:plain

ばらまいているのは別のアクターBPで、花が開くまでの連続したパターンのフリップブックを仕込んでいます。フリップブックの再生速度と、色をランダムにすることでばらつくようにしました。色は緑成分だけランダムにしています(これでピンク色を保ったまま変化します)。

f:id:mi-zmix:20200409172934p:plain

柵とプレイヤーは、ApplyDamageと、AnyDmageで通信して、攻撃が当たった回数だけ数えています。連続してダメージを受けないようにDoOnceを通しました。Damageのピンは未使用なのでつないでません。

f:id:mi-zmix:20200409173243p:plain

3回当たったら壊れたこととして、ひん曲がった絵を表示しました。このとき、タイムラインノードを使ってカラーのアルファで点滅させるようにしました。

背景制作時のルール決め

背景を作る時に気をつけていたことなどを最後に語らせてください。
まず、背景はランダムに選択するので、どの順番につないでもつながるように作る必要がありました。そのため、タイルマップに地形タイルを置く時に、上から7番目のタイルと、一番下2タイル分をかならず共通にすると決めました。左右の端っこの位置をあわせておけば問題なくつながります。あとは端の地形はかならず草地にしました。図の大きさで1マップ分です。こんなのが10バリエーションほどあります。

f:id:mi-zmix:20200414001854p:plain

f:id:mi-zmix:20200414001902p:plain

あと、タイルの配置を考えるときは、上下2段のレイアウトを基準にして、隙間や穴を決めて行きました。下段はたいてい穴があいていて難易度は高めのため、配置する木の場所は多くしました(ランダムででてくるので、かならず下段が多くなっているとは言えないですが)。
上から7番目のタイルの高さは、2段ジャンプしてもぎりぎり届かない位置になります。坂があったら登りたくなる人が多そうなので、上段に上がったらしばらく降りられないという罠みたいなマップも作ったりしました。プレイヤーが通るであろうルートを予測して、誘導したり意地悪したりと、いろいろ考えました。楽しかったですw

おわりに

Grayちゃんのドット絵は自作ですが、音声は公式サイトのデータを使いました。
公式サイトはこちらです。

www.gray-chan.com

「グレイちゃん」で検索すると、ロード・エr(略)のほうが出てきますので、「Grayちゃん」で。

以上です。