LoginSignup
13
3

More than 3 years have passed since last update.

ビンゴマシーンをつくろう

Last updated at Posted at 2019-12-18

Unreal Engine 4 (UE4) Advent Calendar 2019
19日目の記事です

クリスマスが目前に迫ったとある家庭でのお話。

水曜日 深夜

 何かと慌ただしい年の暮れ、夜遅く疲れて帰宅すると、眠そうな目で起きてきた妻に、次の土曜に子供がクラスの友達を連れてきて家でパーティをすることになったと聞かされ、そうかそうかそれは良かったと適当に返事しながら風呂に入ろうとしたところ、「実はビンゴをやることになったんだけど、抽選するマシーンみたいなのが無いのよ」それなら百均とかアプリストアにあるだろう、とパンツを脱ぎながら言うと「それがダメなのよ。パパはゲーム会社に勤めてるからサクッと作ってくれるんだって言っちゃったみたいで・・・」いやちょっと待てそんな時間はないぞ「来てくれる子たちの中に好きな子もいるらしくてものすごく気合はいっちゃってて」しばらく全裸で妻と見つめあっていたらくしゃみが出た。「じゃ伝えたからね、おやすみなさい」といって妻は寝室に戻って行った。

 土曜ってあさってじゃないか!サクッとなんてできるか!しかもプログラマじゃないし!ソファで髪をガシガシと拭きながら考えてみる。
とりあえずUE4で作れそうだけど、とにかくヤバイ。時間もヤバイが見た目もヤバイことになりそうだ。うちPhotoshopとか画像編集ソフトとか入れてないしなあ。絵素材とかなかったらショボイよな・・・
 結局そのまま眠ってしまい明け方に布団に潜ったが仕事に行く時間まで大して眠れなかった。

木曜日 夜

 そして日付が変わる前になんとか帰宅。さっそくUE4のランチャーを起動する。テスト用のプロジェクトが開くまでの間の時間でビンゴについてWikipediaに教えを乞う。カードはすでに百均で買ってきたらしい。会社のイベントでもよく見かける5x5のマスに1~75の数字がランダムに選ばれて並んでいるやつだ。要は1~75の数字をランダムに抽選して表示すればいいだけだろう。ブラウザにはマシーンの画像。Wiiパーティにもあったな。さすがにこれを再現するのは時間が無いし、そもそもサクッと作れるほど技術も無い。
 とりあえずUMGでデッカイ数字出しときゃインパクト出るっしょ。VFXも簡単なやつ入れて、あとストアのアプリも参考にしてポイのを作れば、相手は子供だなんとかなるなる。

起動したので、さっそく Widgetを作って EventGraphをいじりながら仕組みを考える。

ただランダムで抽選すると数字の被りが出るから、
fig00.png
75個の配列に数字を入れてシャッフルして、そこから減らす方が良さそう。

あと抽選の残り数が少なくなると、ランダムだと同じ数字が出て数字が動かないのもカッコ悪いので、ランダム抽選はやめよう。配列とポインター的な変数を用意して、関数を作る。
fig01.png
この関数をつないで、
fig02.png
表示確認だ。とりあえず数字が見たい。
fig03.png
よしデカイ!インパクト大!

抽選する関数はこんな感じかな。
fig04.png

ルーレットの処理と、そこで確定したら配列から引き抜く処理を作らないと。
ここはドキドキワクワクの瞬間だからちゃんと作っておかないと。

木曜 深夜

家族が寝静まって無情に時が進む。なんとかできたぞ。
ルーレット部分のカスタムイベント。
fig05.png
setTimerByEvent 使って、インターバルタイムを引き伸ばしていけばあのデジタルな感じのルーレットが再現できた。条件を満たすまでは何度でもイベントを呼ぶしくみ。
ルーレットが止まるまで 変数Interval を初期化できないので、もう一つカスタムイベントを用意。
fig08.png
このイベント経由でルーレットを回す。なので外からこのイベントを呼ぶ。

確定した時の処理。
fig06.png

ルーレットはゲームパッドとかから入力を受けてスタートするようにしたいので、ProjectSettingsInput にトリガーとしての入力を受け付けるイベントのマッピングを追加しておいた。
fig07.png

テストはレベルブループリントからWidgetをViewportに追加して再生。
fig09.png
Inputに設定したイベント名がノードとして取り出せるので、それとルーレット開始イベントをつなげば、入力を拾ってイベントを呼び出してくれる。

sample.gif

できた!けど地味だ!色が無い!
こういう時は丸いものだ!なんか丸いものを作ろう。マテリアルでできたな。
fig10.png
Imageパーツにこのマテリアルをセットしてキャンバスに追加すれば、ほら!
fig11.png
・・・
なんか間に合わせられそうな気がしてきたけど、
とりあえず今日はこの辺にしておこう。明日も会社行かなきゃ

できたもの

  • ナンバーの表示
  • 入力受付
  • ルーレットの動き
  • ナンバーの抽選

次つくるもの

  • ルーレット中は入力を無視
  • ナンバー確定をわかりやすく
  • ナンバー確定履歴
  • ブラシュアップ

金曜日 夜

なんとか少し早めに帰宅できたので、晩ご飯を温めることもせずかき込んで続きを作りにかかる。
レベルBPでキー入力の受付をとりあえずやってて、そこからWidgetのイベントを呼び出してる。ルーレットが回ってナンバーが確定するとこまではWidget側でやってる。ルーレット中は入力をキャンセルしないといけないからブーリアンでフラグを作ろう。ちゃんと作るならステートの管理をするんだろうけど、とりあえず動けばいいレベルだから、Widget側で管理してしまおう。ボタン入力してもWidget側ではじく!
ついでに確定した時にカラーを変えてみよう。

まずはここから
fig12.png
この isReady が準備OKかどうかの状態を示す。最初は trueで。
レベルBPからルーレットを回せと言ってきやがったら
fig13.png
ここで無視するか決める。
最後までルーレットが回り切ったら、フラグを立てる。
fig14.png

sample2.gif

あとは確定履歴表示だけど、この流れで先に「ルーレット回していいよ」表示を足しておこう。
sample3.gif
フレームインとフレームアウトの2つのアニメーションを用意して、フラグをセットしているところで再生する。ルーレットが回っている間だけ引っ込んでいるようにする。

金曜 深夜

いつの間にか日付が変わっている。今日のお昼に間に合えばいいと言っていた。大丈夫!まだ時間はある!
機能的に残るはナンバー確定履歴だ。ここをしっかり作らないと、ゲーム進行時にグダってしまう。
帰りの電車の中で構造のプランを考えておいたのでさっそく試す。
キモはVerticalBox。
fig15.png
最初に全部 Collapse(非表示)にしておいて、あとから順番に Visible(表示)を増やしていくようにすれば、順番がゴチャらなくていいと思う。見た目にソートしてるように見えると思う。

で、まずは新しく中に入れる子Widgetを用意する。ナンバーが表示できればいい。
fig16.png

Expose on Spawnで数字を書き換えられるようにしておいて、あとはたくさん並ぶ中で目立たせた方が良さそうだからアニメーション入れておこう。
sample4.gif
Visibility を Visible(表示状態)にしたときに一緒に再生できるようにカスタムイベント作っておくくらいでいいだろう。
fig17.png

次はVerticalBoxのWidgetだ。
fig18.png

ヘッダー部分にTextBlockを一つ。これは並べた時に、「B」「I」「N」「G」「O」 の5文字を入れる予定。
すぐ下にVerticalBoxを配置。中身はブループリントから追加する。
fig19.png
ビンゴカードに並んでいるナンバーは、列ごとに配置される範囲が固定されている。開始ナンバーを受け取ってForLoopのIndexに加算することで、使いまわしのできるWidgetになる。

数字が確定したらVerticalBoxの中のナンバー用Widget を Visible にするカスタムイベント。
fig20.png
GetChildAt を使うと VerticalBoxの子要素に対してIndex番号でアクセスできて便利なんだけど、キャスト(型変換)してやれば子要素のWidgetが持つ関数を呼び出せる。

よし、これをルーレットのWidgetに配置しよう。
fig21.png
Expose on Spawn してるやつには Defaultの値として渡す。
B列は 1~15
fig22.png
I列は 16~30
fig23.png
N列は 31~45
fig24.png
G列は 46~60
fig25.png
O列は 61~75
fig26.png

この並べたVerticalBoxの列Widgetをいったん配列に登録しておく。
fig28.png

確定したナンバーをいろいろ計算したら、この配列を通して該当するナンバーを表示させる。
fig27.png

fig29.png

できた。
fig31.png

あ、一応リセットボタン作っておこう。
列用Widgetにイベントを用意。
fig30.png
これで、ナンバーのお団子をすべて非表示に戻す。
これを親のWidgetでイベント作って呼び出すだけ。その際にイロイロなかったことにする。
fig32.png

リセットボタンは、ルーレット開始ボタン同様に ProjectSettings の Inputから追加する。
子供がうっかりボタンを押してしまった時のためにダイアログを作ろうと思ったけど、時間が無いのでちょっと細工する。
ついでにシャッフルボタンも足しておこう。
fig33.png
レベルBPでブーリアンの変数を追加して同時押し判定に使う。初期値を false にしておいて。
fig34.png

これで、キーボードなら Shiftキー押しながら R、ゲームパッドなら Backボタン押しながらStartボタンでリセットだ。
シャッフルは、配列の中身を入れ替えるだけなのでカスタムイベントで簡単。
fig35.png
ナンバーの順番は最初の初期化時にシャッフルしているだけなので、一回のプレイでは固定されている。ほとんど気にならないと思うが、ある程度終盤になると次の番号が予測できてしまう。相手が酒飲みの大人じゃないので一応のシャッフル機能だ。

ふと時計を見ると3時を回っていた。やばい!なんか眠い!

当日 未明

熱いコーヒーをすすりながらビジュアルプランを考える。
ここからはラッシュアップのターンだ。
もっとナイアガラ触っておけばよかったと悔やみつつ何ができるかいじっていく。

とりあえずフォントは変えてポップな感じにして。
背景はマテリアルアニメーションをシリンダーに貼って謎空間を演出してみた。
ss.jpg
無意味にスピード感が出たぞ。

もうちょっと豪華さが欲しい。
あの舞台のピンスポぐるぐるするやつ。
まずは丸いライト用のWidgetを作って楕円軌道を動くようにしてみよう。
fig36.png
マテリアルは最初の方で作った円を複製してブレンドモードを Additive(加算)にする。
fig37.png
なんとかいい感じの動きができた。
カラーと角度を初期設定できるようにExpose on Spawnしておく。
これを親のキャンバスに3つほど配置すれば・・・うんいいね。あとテキストも固いから変更しておこう。
ss2.jpg

できた!
けど、もうちょっと何かこう・・・
お、こんなところに素材発見。PNGだから落とせば使えそうだ。
よしよしこれをこうやって、こうして、つないで・・・できた!

いつのまにか外が少し明るくなっている。
仕事でもないのに朝チュンしてしまった。
これで悔いはない。あとは見守るだけだ。ハッピークリスマス!

サンプルの動画 → https://youtu.be/FR1AZbfpt-U

あとは寝るだけ

というわけで、ちょっとボリュームが出てしまいましたが、いかがだったでしょうか。
ナレッジ的なお役立ち情報とかではないのですが、アドベントカレンダーということで遊べるものを作ろうと思って、ビンゴマシーンをネタにしてみました。グラフィック素材はGrayちゃんとフォント以外は現地調達です。
できることがあらかじめ分かっているので、アレンジもしやすいし、UE4の手習いにちょうど良い教材だと勝手に思ってます。
ハンズオンとかで皆で作って遊ぶとか。それぞれのセンスやこだわりが思い思いに表現されて楽しそうです。
この時期、時間の惜しい中最後まで読んでくださってありがとうございます。

みなさまよいクリスマスを過ごせますように。

13
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3