Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php on line 340

Warning: Cannot modify header information - headers already sent by (output started at /home/squirrel/www/surfrog/web/wp-content/plugins/crayon-syntax-highlighter/crayon_langs.class.php:340) in /home/squirrel/www/surfrog/web/wp-includes/feed-rss2.php on line 8
開発 | おかしくカエル! http://surfrog.net かえる好きエンジニアによるアプリや真面目~おふざけ文章まで Wed, 19 Apr 2017 06:11:24 +0000 ja hourly 1 https://wordpress.org/?v=6.2.5 http://surfrog.net/web/wp-content/uploads/2016/04/cropped-site_icon-32x32.png 開発 | おかしくカエル! http://surfrog.net 32 32 UE4ぷちコン作品 クレーンゲーム製作記④ エンディングを作る http://surfrog.net/2017/04/19/ue4-create-game-4/ http://surfrog.net/2017/04/19/ue4-create-game-4/#respond Wed, 19 Apr 2017 14:00:36 +0000 http://surfrog.net/?p=3610 クレーンゲーム製作記、最後はエンディング画面についてです。

レベルシーケンスを使う

クリア条件を満たした後は、ムービーを流してそのままエンド。これを実現するのがレベルシーケンスというムービー機能です。シーケンサーに関しても公式ドキュメントが充実していました。ありがたやー。

レベルシーケンス

Add Level Sequenceで開始。マチネというのは以前までに使われていた同様の機能みたいです。

シーケンサーエディターは動画編集ソフトのような感じで直感的に操作できるので、カメラを操作したりしてキーフレームを打ち込み、ムービー部分を作って行きます。

イベントのトリガー

イベントトリガー

イベントのトリガーに関しては、追加→イベントトラックでイベントを追加した後、キーフレームを打ち、Event Nameを設定することで、Custom Eventとして呼ばれます。

 

イベントの受取

イベントトラックのEvent Nameとブループリント内のCustomEvent名が合っていれば、イベントを受け取ることができます。

 

シーケンサーの再生

出来たシーケンスの再生はCreate Level Sequence Playerで取得してPlay。簡単。

 

そんなこんなでエンディング画面が完成して、「さプライズ」の完成です。

 

後書き

1つの作品作りにむけて楽しめました。

Unreal Engine4のデモサンプルは好きに使っていいという太っ腹っぷりがEpic GAMESの凄いところ。各種アセットは高品質なものがそろっており、もっとクオリティアップできたかなという思いはあります。とはいえ、こういうのは自分でも作ってみたくなるし、サクッと作ってサクッと応募なら自分で作るのもまた一興。そんなわけで慣れないBlenderを使って3Dモデルも自作しました。

 

Unreal Engine4は初めてで、いきなり開発環境としては全く小さくないものなので、最初はどこを触っていいか戸惑いましたが、ブループリントを見た時のスッと入ってくる感じは良かったです。何かこう…私はあらためてデザイナー方面ではなく、プログラマ方面なんだなと思いました。

実は最初に学ぶ際に選んだビデオがC++でTPSゲームを作るというもの。

なんか結構ややこしい上にC++ガッツリ使うんだな…

なんて思っていたのですが、他のドキュメントを見たら全然使わなくてビックリ。結局今回のクレーンゲームも自前でC++に触ることはありませんでした。このあたりはぷちコン主催者様であるヒストリアさんの記事「C++ or Blueprints?」にもブループリントで実現可能なものはブループリントで実装する、とあり、その通りだと非常に思いました。

 

次はC++も使って何か作品を作れたらいいなぁと思った次第です。第8回も参加するつもりです。Tシャツ欲しいし。

 

 

ではでは。

]]>
http://surfrog.net/2017/04/19/ue4-create-game-4/feed/ 0
UE4ぷちコン作品 クレーンゲーム製作記③ ゲームセンターを作る http://surfrog.net/2017/04/11/ue4-create-game-3/ http://surfrog.net/2017/04/11/ue4-create-game-3/#respond Mon, 10 Apr 2017 16:00:59 +0000 http://surfrog.net/?p=3655 前回はクレーンゲームを作りました。今回はクレーンゲームを配置するゲームセンターについてです。

 

ゲームセンターを作る

ゲームセンターを作っていきます。

ゲームセンター

作ったクレーンゲームを複数設置。何かこれだけでもゲームセンターっぽくなりました。ゲームセンターを構成する要素にクレーンゲームって凄いある気がする。人のイメージとして。

ディレクショナルライト

ついでにゲームセンターといえばやっぱり夜なので、SkyLightは削除して、DirectionalLightを上向きにします。

ライト設置

真っ暗になるので、光源を大量に設置します。ライトは全てスタティックライトです。ここまで追加するとビルド時間がかなり長くなります。

 

ゲームセンター

光源を設置してビルドしたらゲームセンターの雰囲気が出てきたように思えます。

 

エディターだけ自動露光を削除する

夜のゲームセンターの演出のために、太陽光を無くして店内の明かりをいっぱい設置したために、店内から店の外に視線を移動させると、自動露光の効果によって真っ暗になります。

ゲームセンター外

店の外に視線を変えたところ。真っ暗です。

この自動露光の効果自体は人間の目の視覚効果と同じで、ゲームの雰囲気作りに一役買っている。なので実行時は自動露光をオンで、エディタ上でだけ自動露光を切りたい。調べてみるとビューポートのライティングのところにありました。

自動露光の設定

露出がAutomaticになっているところを、固定にすれば解決です。

 

 

モブを配置する

自分しかいないゲームセンターは寂しいので、モブとしてデフォルトのマネキン(ブルーマン)を配置します。

マネキン

このままではさすがに違和感バリバリなので、推理モノに出てくる黒い人のようにしてみたいと思います。

黒い人

マテリアルのシェーディングをUnlitにして単色で塗りつぶします。

ビルボード

ついでに肩書きを表示するために、ビルボードを作ります。

カスタムデプス

CustomDepth Passを有効にして、常に前面に表示できるようにします。

黒い人肩書

ゲームセンター内にいる客…のような正体不明の人ができました。

 

吹き出し

吹き出しも「客」肩書きテキストと同じように、ビルボード+CustomDepth Passによる常に前面にレンダリングしています。

 

 

モブを動かす

モブができたらゲームセンター内を徘徊するようにします。AIについては公式ドキュメントに詳しく書かれています。ドキュメントにあるようなBehaviorツリーを使わなくても、ランダムで徘徊させるぐらいなら簡単にできます。

NavMeshBoundVolume

NavMeshBoundsVolumeを追加して、動ける範囲を設定

ランダム徘徊ブループリント

後はGetRandomReachablePointInRadiusでランダムに移動できる点を取得、SimpleMovetoLocationでその地点まで動かすことができます。

これを定期的に行えばモブのランダム徘徊は可能です。全く賢くはないですが。

 

 

ゲームセンターの小物を配置

説明不要ですが、小物を配置していきます。

両替機

両替機、ゲームセンターに必須ですね。動かないけど。

ポスター

ポスター。ゲームセンターに貼ってあるポスターは欲しくなります。椅子はスターターコンテンツのものです。でもサンプルのメッシュを使っていいというのも中々オツですね。

エレベーター

こっちはエレベーター。ドアが開閉するようになってます。

自動ドア

デモサンプルにも自動ドアがありましたが、ドアの開閉はタイムラインを使うといい感じにできます。開ける時はPlayに接続してタイムラインから出てくる数値に従ってドアのlocationを操作する。閉める時はReverseに接続だけでOK。

 

ゲームセンター

できたゲームセンターがこちら。

 

ゲームセンターの外も作る

入り口はガラス製のドアで外が見えるので、店の外も見える範囲で作ります。

ゲームセンター店外

画像はスカイライトで明るくした状態でのスクリーンショットです。

 

道路に通行人や車をスポーンさせる

ゲームセンター店外

こちらも明るくした状態での動画です。店の前を車と通行人が通るようにして喧騒な感じを出します。

 

スポーン

やり方はブルーマンをスポーンさせた後、移動させると同時に、

ライフスパン

SetLifeSpanで寿命を設定します。これで自動でDestroyされるので後は適当な間隔でスポーンさせればランダムな通行人が完成です。

 

車

車の方も同じようにしていますが、こちらはランダムで色を変える処理とリボントレイルによるテールランプの尾を引くようなエフェクトを入れています。AnsqweHubのココが参考になりました。

 

 

ポーズとゲームのやり直し

ポーズ

ポーズはSetGamePausedだけで動作します。超楽。ポーズ画面を表示して、解除やゲームのやりなおしを選択するので、ShowMouseCursorでカーソルを表示します。

 

ポーズ

ポーズ画面

RestartGame

ゲームをやりなおす際はRestartGameを呼び出すだけで各種設定がリセットされてリスタートできます。ポーズとリスタート共々非常に楽です。

 

これクレーンゲームが大体完成しました。後はエンディング画面です。

 

ではでは。

]]>
http://surfrog.net/2017/04/11/ue4-create-game-3/feed/ 0
UE4ぷちコン作品 クレーンゲーム製作記② クレーンゲームを作る http://surfrog.net/2017/04/10/ue4-create-game/ http://surfrog.net/2017/04/10/ue4-create-game/#respond Mon, 10 Apr 2017 14:00:39 +0000 http://surfrog.net/?p=3547 前回、タイトル画面の製作記についてあれこれ書きました。今回はゲーム本編、クレーンゲームそのものの製作についてです。

 

どういうゲームにするか

ぷちコン応募作品を作るにあたって思いついたクレーンゲームシミュレーター。ただ固定のカメラでクレーンゲームを作って遊ぶよりかは、やはりUnreal Engine4のパワーを使って、クレーンゲームがいっぱい置いてあるゲームセンターみたいなの作って歩き回りたいと思いました。そういうことが簡単に実現できるのがUnreal Engine4というゲームエンジンだとも思ったので。

そんなわけでゲームセンターを歩き回って、クレーンゲームを操作するFPSタイプのゲームに決定しました。

 

後はゲーム性です。現実のクレーンゲームを考えた時、いかにお金を使わずに景品を取れるかということが目標だと思います。そしてクレーンゲームで景品が取れる時というのは、アームが強い時です。全然取れない時もあれば、簡単に取れる時もあるアームの強度を演出できれば、目標というのが生きてきます。ついでに、昨今の全然掴んで取れないクレーンゲーム事情(ずらして取る…みたいなの)を実現できればいいとも思いました。

 

操作に気をつける

FPSというゲームは操作が複雑です。WASDに加えてshiftとctrlとspaceとマウスの操作。

私はSteamのゲームをよくプレイしますが、FPSのゲームにはアクションキーもしくはインタラクトキーと呼ばれるものが多くあり、キャラクターのアクションを1つのキーに集約してしまうといったのがよく見られます。

物を取るボタンはR、奥ボタンはFといった具合に分けるのではなく、HUDで状況を表示することによって、1つのボタンで色々できるインテリジェンスなキーとして集約させることによって、ただでさえややこしいFPSの操作キーの煩雑さを回避するのに一役買っています。

ゲーム操作

Payday 2のインタラクトキーの例。鍵を開ける、カードキーを通す、人質をタイで縛る、現金バックを拾う、現金バックを投げるといったアクションのほとんどを担当するのがFキー。HUDに表示されるために今インタラクトキーで何が行われるかということも理解できる。便利かつ煩わしさが無いのが好きです。

 

というわけで「さプライズ」にもこのインタラクトキーを導入します。クレーンゲーム機に近づいたら状況によって

  • コインを入れる
  • 横移動
  • 奥移動
  • それ以外(クレーン動作中の待ち状態)

を1つのキーで全て行えるようにします。

 

ゲーム操作

これは特に難しいことはなく、インタラクトキーに割り当てたキーが押されたら、状況によって操作を変えるだけです。

 

さプライズの肝。クレーンゲームの物理シミュレーション

このゲームの肝はなんといってもクレーン部分の物理です。そのためクレーンの動作に関してはある程度妥協せずに物理を実現させたい。そのためには物理コンストレイントというのを使います。

物理コンストレイントは物理物体を接続するジョイントで、角度制限や移動制限を付けたり、移動エネルギーを加えることができます。

 

Unreal Engine4の公式ドキュメントに物理コンストレイントについて記載されていますが、
ウィジェットの時と違い、物理コンストレイントの説明はサラッとしていて、自分でトライアンドエラーを繰り返してアームの開閉ができました。なので忘れないように開発記を残しておきます

 

まず、物理コンストレイントには2つのメッシュが必要です。

UFOボディ

アームの接続元となるUFOのパーツ。

 

UFOアーム

アーム本体。

 

この2つを物理コンストレイントで接続していきます。

コンポーネントの追加ボタンを押してPhysicsConstraintを選びます。

物理コンストレイント接続

PhysicsConstraintをクリックして詳細を開き、アーム接続元となるufoをComponent Name 1に、アームをComponent Name 2に設定します。選択タブとかは無く、キーボードでコンポーネント名を打ち込むだけです。

これでビューポートにてufoとアームが青と赤の立方体で囲われていたら物理コンストレイントは動作しています。Disable Collisionにチェックを入れると、物理コンストレイントで接続した物体同士の衝突が無視されます。今回はチェックを入れています。

 

続いてはアームを動作させる角度の設定です。アームの開閉角度は45度で、1方向のみという事を考えつつ数値を設定していきます。

平行移動に関しては移動させないので全てLockedで固定。

Angular Limitsがアームの開閉に適した部分です。Twistのみ有効にして、中心から両側22.5度動作するように設定します。

設定した後がこちら。物理コンストレイントがアームの回転軸になるため、物理コンストレイントの位置もキッチリ合わせておく必要があります。

 

物理コンストレイントの子パーツであるアームメッシュのSimulate Physicsを有効にすると、物理コンストレイントをシミュレーションで確認することができます。なお、物理コンストレイントを使用して動作させるメッシュは、プリミティブなコリジョンでないと警告が出ます。

アームのコリジョンはカプセルなどを使用して設定しています。

 

物理コンストレイントの実行

当然ながらアームに対してエネルギーを加えていないため、実行しても何も起きません。ただし、外から力を加えてもアームの開閉以上の動作はしないようになっています。

 

アームを開閉させる

物理コンストレイントのエネルギー

物理コンストレイントの詳細、Angular Motorのところでエネルギーを加えることができます。大きく2つの方法があり、Target Orientationはその角度へ持っていくためのエネルギーが発生します。Target Velocityはその角度方向のエネルギーが発生します。

アーム開閉方向へのエネルギーを加えてみます。Target VelocityのXを22.5、Twistにチェックを入れて、シミュレーションをスタートさせます。

アーム開閉

アームが開きました。このままでは遅いので、Strengthを10倍の10.0などにすると早くアームを開くことができます。

アームとUFO部分のコンストレイントができたら、他の物理コンストレイントも加えていきます。

クレーンゲームの物理コンストレイント

最終的にはアームの左右開閉、UFO部分の上下移動、横移動、奥移動と5つの物理コンストレイントを使いました。

 

物理コンストレイント微調整ポイント

ここから先は微調整に微調整を重ねることになりますが、微調整のポイントを整理します。

Linear Motor、Angular Motor

物理設定

物理コンストレイントのMotor部分はエネルギーを生み出す設定そのもの。LinearもAngularもあまり変わらず、その場所に持っていく設定がPosition Target、Target Orientationです。エネルギーのベクトルを指定するのがVelocity TargetとTarget Velocityです。

例えばPosition TargetをX 100.0に設定すれば、X 100.0方向に向かうエネルギーが常に発生します。X 0の位置ある場合は+方向のエネルギー、X 200にいたら-方向のエネルギーといった具合です。

Strengthはエネルギーの強度です。

 

Linear Limits、Angular Limitsの詳細設定

物理設定

物理設定

物理コンストレイントに違反(制限値に触れた場合)の動作設定。例えばSoft Constraintにチェックを入れると、スプリングのように反発する動作が得られます。アームを開いた時のように、バシッと止めたい場合はSoft Constraintのチェックを外し、Restitutionを0.0にして反発しないようにすると、アームっぽくなりました。

 

物理コンストレイントの子パーツの物理設定

物理設定

物理コンストレイントで接続したメッシュの物理設定も微調整のポイントとしては重要です。

Linear DampingやAngular Dampingはデフォルトでは低すぎるので、少し上げた方が良い事が多いでしょう。

例えば前述のPosition Targetを使ってエネルギーを発生させる場合、X 100を指定して、X 0にある物理メッシュを動作させるとします。実行するとX 100まで物理メッシュが動作した後、制限が無い場合はX 125などといった数値まで滑ります。そうなるとまたX 100に向かって動作するのでX 80、X 110といった具合に設定した値を行ったり来たりします。Linear Dampingの数値をすこし上げることでこの行ったり来たりを抑える摩擦のようなものが発生します。

 

また、Angular Motorで回転させたりする場合はCenter Of Mass Offset(重心)も重要です。クレーンゲームのアームも、重心が中心にありすぎると簡単に掴んで運べてしまうため、アームの弱さを演出するために重心をアームを開く側に設定しています。

 

ブループリントで制御する

各種物理の設定が固まったら、エネルギーの方はブループリントで制御できるようにします。

アームの開閉

Angular Motorは、SetAngularVelocityTarget、SetAngularDriveMode、SetAngularDriveParamsで設定できます。

 

 

クレーンゲームを完成させる

アームが制御できたら、クレーンゲームを肉付けしていきます。

クレーンゲーム肉付け

メッシュを配置しているぐらいで特にテクニカルな事は無し。Arrowは景品の配置用に追加しています。

getworldtransform

GetWorldTransformでTransformが取得できるので、景品の配置位置の調整に便利です。

 

クレーンゲームの動作を状態を分けて考えて

  1. アイドル状態(コイン投入待ち)
  2. 横移動
  3. 奥移動
  4. クレーン操作(アームの開閉とボディの昇降)
  5. もとの位置(穴の位置)に戻ってアームを開閉
  6. 1に戻る

ステートマシンとしてブループリントを記述していきます。

ステートマシン

スケルタルメッシュのアニメーションの方はステートマシンを使えたのですが、Actorのブループリントで使えないので、昔ながらのSwitchによる処理分けです。ブループリントをたくさん使うだけで、特に難しいことはしていません。

 

最終的なアーム動作はサイズが大きくてgifでは無理そうなので応募作品から確認して見て下さい。

 

長くなってので一旦ここまでにします。次はゲームセンターの店内についてです。

 

ではでは

 

]]>
http://surfrog.net/2017/04/10/ue4-create-game/feed/ 0
UE4ぷちコン作品 クレーンゲーム製作記① タイトル画面を作る http://surfrog.net/2017/04/07/ue4-create-game-2/ http://surfrog.net/2017/04/07/ue4-create-game-2/#respond Thu, 06 Apr 2017 16:00:32 +0000 http://surfrog.net/?p=3522 ぷちコンは動画で応募な上に、サクッ作ってサクッ応募のキャッチコピーな以上、タイトル画面やオプション画面、ヘルプだったりは最悪見せなくても何とかなるレベルであり、間に合わなければ削られる部分ではあると思います。時間も限られていますしね。

ただ、せっかく1つの作品を作るので、ゲームとして必要な部分を揃えたいと思うのもまたクリエイター。タイトル画面~ゲーム中~エンディング画面といった遷移は考えてみます。

ゲーム構想

ゲームの遷移ってこんな感じですよね。そんなわけで今回はタイトル画面についてです。

 

タイトル画面

ウィジェット

タイトル画面を構成するゲームタイトルやスタートボタンはUMGで実現可能。UMGに関しては公式ドキュメントが充実していました。

UMG

ウィジェットを作成してパレットからテキストやイメージ、ボタンといったパーツを配置していくことで作成。

UMG

大体こんな感じになりました。

 

UMG

レベルブループリントにてウィジェットを追加。

 

UMG

このままではFirst Personキャラクターが持つキーの移動が効いてしまうので、入力をUIのみにすることと、ついでにカーソルを表示する処理も加えると完成です。

 

これで起動するとタイトル画面のウィジェットの表示されます。

 

タイトル画面の背景

後はタイトル画面の背景をどうするかということですが、「さプライズ」ではゲーム中の画面を背景として使い、シームレスにゲーム状態に移行させることを考えました。

 

ゲームセンター

色々配置したゲームセンターの建物。これを背景として使います。

 

タイトルカメラ

カメラ(TitleCamera)を設置。カメラを右クリックしてパイロットモードにするといい感じのところに持っていきやすい。

 

カメラを設定してもまだ有効にはなりません。この「さプライズ」では、First Personプロジェクトをテンプレートとして使っているので、デフォルトでカメラの設定はキャラクターの持っているカメラになります(FirstPersonCharacterのFirstPersonCamera)。

カメラの制御を移すやり方は色々ありますが、今回は起動時にタイトル用のカメラにターゲットを変更する方法を使います。

タイトルカメラ

レベルブループリントのBeginPlayにて、SetViewTargetwithBlendを使ってカメラを切り替えます。

 

カメラ処理

これで起動時にカメラがTitleCameraになるので、ウィジェットのボタンを押したときにはFirstPersonCameraに戻るように処理を追加します。BlendTimeに少し値を設定することで、カメラの切り替わり中を補間してくれます。

 

ちなみにFirstPersonCharacterの初期位置はココ。扉入ってすぐのところです。

実行するとこんな感じにシュッとカメラが移動します。後はウィジェットを消せばゲーム中への遷移が完成です。

ウィジェット削除処理

ウィジェットのボタンを押した時の処理に、ウィジェットの削除、カーソルの表示処理、入力処理の制限を解除を追加します。

これでタイトル画面からプレイ中へシームレスな移動ができました。

 

実際の完成版では扉を開けて閉める処理やサウンド、カメラの調整を行ったため、Level Sequenceも使っていますがが、遷移部分の処理としては同じです。

 

 

感想:Unreal Engine4はゲームから作るゲームエンジン

Unreal Engine4を触るのは初めてだと製作記の冒頭で書きました。

前はCocos2d-xを使っていましたが、そちらはC++を使うプログラムばりばりのテキストベースのゲームエンジンで、

さぁ作るぞ!

って思ってから、とりあえずゲームにはタイトル画面があってから、ゲーム画面。よし、タイトル画面を一旦先に作っておこうか…いやその前に抽象クラスを…みたいなイメージなわけです(私だけだったらスミマセン)。

 

Unreal Engine4ではプロジェクトを新規作成したら謎の青い男が動いていて、タイトル画面を作ることをスッカリ忘れて遊んでいました。いくぶんテキストベースよりもゲームを作りやすい気がします。とはいえ、Unreal Engine4でもゲームとして完成させることを考えた場合にはタイトル画面や独自のデータを取り扱う必要が出て来きます。データの取り扱いに関してはブループリント上では構造体とか列挙型の扱いがちょっと面倒くさいと感じてたりします。

 

次はゲーム本編、クレーンゲームの製作記です。

 

ではでは。

 

]]>
http://surfrog.net/2017/04/07/ue4-create-game-2/feed/ 0
第7回ぷちコン応募作品、製作記 http://surfrog.net/2017/04/04/puti-contest/ http://surfrog.net/2017/04/04/puti-contest/#respond Tue, 04 Apr 2017 14:30:41 +0000 http://surfrog.net/?p=3512 先日行われたぷちコンにて、Unreal Engine4で作ったゲームを提出しました。
備忘録を兼ねて、制作記を書いていこうと思います。

 

ざっくり最初から書いてたら結構な量になってしまい、今回は応募作品の紹介とさわりのさわりの話だけです。

 

応募作品「さプライズ」

クレーンゲームシミュレーション。

昨今のゲームセンターのアーム事情を再現したかったので、わりとアームが弱くて掴めません。ずらして落とすゲームになっています。もうそれはクレーンゲームじゃない気もするんですけどね(笑)。

ゲーム性を出したかったので、筐体によってアームの強弱を設定し、それを推測できるように周りの客がつぶやくという形になっています。そして最終的にはどれだけお金を使わずに景品を取れるかというリアルな目標になっています。

 

製作記

テーマ「サプライズ」について

今回のぷちコンのテーマは「サプライズ」

いくつか思い立ったのですが、その中には軍艦の「サプライズ」というものがありました。結果的にはそっち側で応募したら被ることになる上に、3Dモデルの作り方がいまいちよくわかっていない私としては恥をかくところでした。

しかも私自信、ミリタリーにあまり詳しくないですしね。

 

そんな私が採用したのは「さ」プライズ。

プライズ=景品

よって「さ」を景品としたクレーンゲームという駄洒落。

Cocos2d-xを使ってた私としては、Unreal Engine4の物理についてはちょっと気になっていたのでこの際物理シミュレーションも試してみようとも思ったわけです。

 

Unreal Engine4は凄い

実は3Dのゲームエンジンを初めて触ることになります。といってもぷちコンが始まってからではなく、その前から興味があってちょこちょこ触っていました。

Unreal Engineといえばゲーム好きはまず知っているゲームエンジン。Unreal Tournamentも遊んだ経験あります。採用ゲームで遊んだことのあるゲームを列挙すると大変なので、中でも好きなものといえばGears of WarとかBorderlandsでしょうか。最高ですね。

 

Unreal Engine4の準備は簡単、インストールするだけです。説明不要。

Unreal Engine4新規プロジェクト作成画面

インストールできたらUnreal Engine4の世界に飛び込めるようになります。

新規プロジェクト作成で、名前をHelloWorldと打ち込んだ後の凄い大きな世界へ放り出された感は半端ない。どこから何を知ったらいいかもわからない。

Unreal Engine4画面

何をしたらいいのか……開発環境というのはどうしてこうややこしいのでしょう(笑)。

ただ、そんなに悲観することはありません。Unreal Engineは日本語のドキュメントが充実している上、プレイを押すだけで綺麗な3D世界に突入可能です。ここまでのを作るのにOpenGLやDirectXだけだったら大変ですよねぇ。いい時代になったものです。

 

そんなこんなでビュー操作やオブジェクトの配置など、基本的な操作については操作しながら何となく理解できました。

 

ブループリント

ゲームに欠かせないスクリプト・プログラムを担うのがこのブループリントと呼ばれるフロー図のようなもの。ブループリントというのは日本語で設計図という意味です。

 

プログラムをちょっとでも触ったことのある方は、次の画像だけでどういうものか理解できると思います。

ブループリント

何となくBeginPlayからスタートして、条件分岐やループを使いつつPrint。理解可能ですね。

 

ブループリント実行結果

実行結果はもちろんテキストがprintされます。画面上ですがログ上にも出ます(出せます)。

 

このブループリントはテキストベースのプログラムだと下記のような感じですね。

void BeginPlay() {
    PrintString("Hello");
    
    if( Now.GetHour() > 12 ) {
        PrintString("午後");
    } else {
        PrintString("午前");
    }
    
    for(int i=0;i<10;i++) {
        PrintString(toString(i));
    }
    PrintString("GoodBye");
}

いかかでしょう、ブループリント。

私はどちらかというとプログラム畑の人間なので、ブループリントはプログラムと親和性が高いところが好みです。ついでにUnreal Engineではその気になればC++で打てるところもいい所です。基本はブループリントで記述して、できないことがあればC++を使っていく感じだと思います。でも大体の事はブループリントで事足りるでしょう。

 

 

Unreal Engine4を触った感想しか書いていませんが、長くなってきたのでとりあえず今回の製作記はここまでにします。

 

ではでは

]]>
http://surfrog.net/2017/04/04/puti-contest/feed/ 0
【10円ゲーム講座】第13回 デモ画面を実装してみる http://surfrog.net/2016/08/16/cocos2dx-tutorial-13/ http://surfrog.net/2016/08/16/cocos2dx-tutorial-13/#respond Tue, 16 Aug 2016 12:00:12 +0000 http://surfrog.net/?p=1249 Cocos2d-x

Cocos2d-x 10円ゲーム講座 第13回、デモ画面を実装します。

第12回はこちら目次はこちら

 

デモ画面って?

これまででゲーム部分は完成しています。デモ画面は蛇足といっても過言ではありません(笑)。

タイトルを作ってシーン遷移、というのがチュートリアル的にはシーン遷移を学べて良いかもしれません。しかし、10円ゲームにタイトルからのシーンチェンジは不要でしょう。コインを入れてサクッとスタート。現実世界でもサクサク感は10円ゲームの醍醐味の1つだと思います。

私の思い出ですが、駄菓子屋に置いてあるゲーム機のデモ画面が好きでした。今でもそうですが、筐体機のデモ画面って非常に楽しそうな感じがしますよね。お菓子にするか、ゲームをするか……どれにお金を使おうか迷ってた子供時代、デモ画面は効果的な宣伝だったように思います。

 

そんなわけで、10円ゲームにコインを入れるまではデモ画面にしてみます。現実世界の10円ゲーム機のデモプレイはありえませんけどね。

 

デモ画面を考える

前置きが長くなりましたが、10円ゲームのデモ画面というのを考えてみます。

  • ゲーム起動時や失敗、クリア後のコインが筐体に無い状態が一定時間続けば、デモモードに移行する
  • デモモード時は
    • コインが無ければ自動で投入
    • コインがレバー位置にあれば、ランダムな力ではじく
    • デモプレイ画面であることを明示する
  • デモモード解除の方法
    • コイン投入口ボタンのタッチ

こんな感じでしょうか。

 

デモ画面用

デモプレイ画面であることは、このDEMO PLAY文字を明滅させることにします。

 

説明する部分は少ないのでコードを載せていきます。

class OneCoinGame : public cocos2d::Layer
{
public:
	// DEMO画面用update
	void demoUpdate(float delta);
private:
	// デモモード
	bool			_isDemo;
	cocos2d::Sprite	*_demoSprite;
};

デモ画面用のスケジュール関数と変数の定義です。

 

// デモモードかどうか
_isDemo = false;
// カスタム定期処理の開始(5.0秒毎の呼び出し)
this->schedule(schedule_selector(OneCoinGame::demoUpdate), 5.0f);

コインの監視の際に説明したscheduleUpdate()メソッドはフレーム毎にupdate(float delta)を繰り返す呼び出す処理と決まっていましたが、デモ画面用のスケジュール処理は毎フレーム呼び出す必要はありません。そういった場合にschedule()を使用することで任意のメソッドを任意の間隔で呼び出す処理が可能です。今回は5.0秒毎に1回demoUpdate()を呼び出します。

 

// デモモード時の更新処理
void OneCoinGame::demoUpdate(float delta)
{
	// デモ状態かどうか
	if (!_isDemo) {
		return;
	}

	// coinの状態を確認
	// Enableがfalseなら、コイン投入処理
	if (!_coin->getPhysicsBody()->isEnabled()) {
		this->coinEntry();
	}

	// コインがレバー位置にあるなら、レバー処理
	for (int i = 0; i < 4; i++) {
		// 範囲内ならコインにランダムな力を加える
		if (leverArea[i].containsPoint(_coin->getPosition())) {
			auto power = CCRANDOM_0_1();

			if (i == 0 || i == 2) {
				this->applyForceCoin(1.0f, power);

				_lever[i]->setRotation(power * -90);
				_lever[i]->runAction(RotateTo::create(0.2, 0.0f));
			}
			else {
				this->applyForceCoin(-1.0f, power);

				_lever[i]->setRotation(power * 90);
				_lever[i]->runAction(RotateTo::create(0.2, 0.0f));
			}

			// 効果音を鳴らす
			CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("se/lever.wav");
		}
	}
}

CCRANDOM_0_1()はCocos2d-xでランダムを扱う場合に便利なマクロです。0~1までのfloat値を返してくれます。その他の説明は特に新しいことをしていないので省きます。

DEMO PLAYの明滅は、フェードイン・アウトの繰り返し処理で実現しています。Blinkを使わない理由としては、Blinkの点滅処理はbVisibleを操作するため、ボタンを押した際のsetVisibile処理と不整合が出るためです。ちなみにFadeIn, FadeOutはopacityを操作します。

 

実行結果

デモプレイ。どうでしょうか。ソースコードはこちら

 

私はこういう勝手に操作しているのを眺めるのは大好きです。ランダムに力を加えているだけですが、見ていると結構楽しいですよね。

]]>
http://surfrog.net/2016/08/16/cocos2dx-tutorial-13/feed/ 0
【10円ゲーム講座】第12回 パーティクルを使ってエフェクトを発生させる http://surfrog.net/2016/08/12/cocos2dx-tutorial-12/ http://surfrog.net/2016/08/12/cocos2dx-tutorial-12/#respond Fri, 12 Aug 2016 12:00:52 +0000 http://surfrog.net/?p=1244 Cocos2d-x

Cocos2d-x 10円ゲーム講座 第12回、パーティクルを使ってエフェクトを発生させます。

第11回はこちら目次はこちら

 

エフェクト処理

10円ゲームにパーティクルを使ってエフェクト処理を施してみます。

パーティクルとは粒子のことで、小さな画像を多量に使い、ひとつひとつに動きをつけることでエフェクトを表現するものです。これはもう実際にパーティクルを作成するエディタを触ってもらった方が早いと思います。

http://particle2dx.com/

有名なパーティクルエディタ。パーティクルエディタはいくつかありますが、こちらはフリーで使えるのでオススメです。

 

ササッとあれこれ弄ってパーティクルが出来たら、

particle2dxの出力

出力はExport → COCOS2DXをクリックすればparticle_texture.plist(デフォルトファイル名)がダウンロードできます。

 

今回作成したパーティクルはこちら。コイン投入時に火花を散らすようなシンプルなエフェクトです。

Cocos2d-xではパーティクルのplistをそのまま読み込んで使用することができます。

// パーティクル処理
auto particle = ParticleSystemQuad::create("particle/particle_texture.plist");
particle->setPosition(Vec2(visibleSize.width*0.7, visibleSize.height*0.9));
particle->setAutoRemoveOnFinish(true);		// パーティクルが終了したらNodeを削除する
this->addChild(particle, 3);

パーティクルを使うにはParticleSystemQuadクラスを利用します。setAutoRemoveOnFinish(true)をしておけば、パーティクルが終了した際に自動で削除してくれるので便利です。
無限ループを設定しているパーティクルは当たり前ですが自動で削除されないので注意しましょう。

 

実行結果

ソースコードはこちら

 

エフェクトの回でも書きましたが、10円ゲームはレトロさがウリでもあるので過度なエフェクトは不要な気もしますね。

 

次回はデモ画面の実装です。

 

]]>
http://surfrog.net/2016/08/12/cocos2dx-tutorial-12/feed/ 0
【10円ゲーム講座】第11回 スプライトアクションを使ってユーザビリティを向上させる http://surfrog.net/2016/08/09/cocos2dx-tutorial-11/ http://surfrog.net/2016/08/09/cocos2dx-tutorial-11/#respond Tue, 09 Aug 2016 12:00:20 +0000 http://surfrog.net/?p=1242 Cocos2d-x

Cocos2d-x 10円ゲーム講座 第11回、スプライトアクションを使ってユーザビリティを向上させる方法についです。

第10回はこちら目次はこちら

 

ユーザビリティの向上

ゲームの骨格となる部分は完成しました。1つ問題点を上げるならボタンがボタンと解りづらいことです。つまりユーザビリティが悪いということです。

レバーは見た感じでわかるかもしれませんが、お金の投入口がボタンになっていることは、パッと見ただけではよくわからない可能性もあります。

 

ボタンホバー

 

スマートフォンの台頭で、マウスではなくタッチ操作が主流になってきました。マウスの場合は、マウスオーバーという手法によりボタンがボタンであることを明示できました。

しかし、タッチ操作ではマウスオーバーに相当する操作がありません。

 

ボタンを明示するよくある方法としてはグロウ処理を行うことです。ボタンを淡く光らせることで、ユーザーに装置であることを明示することができます。今回はボタン投入口とレバーにグロウ処理を施してみます。

 

用意したグロウ画像です。

コインの投入口のグロウ

レバーのグロウ

 

グロウ画像をこれまで同様、Spriteクラスを使って表示します。

auto sprite = Sprite::create("coin_entry_glow.png");
sprite->setPosition(Vec2(visibleSize.width*0.7, visibleSize.height*0.9));
this->addChild(sprite, 2);

 

グロウ処理のためにSpriteにアクションを設定します。

// アクション
auto blink = Blink::create(1.5f, 1);			// 点滅 1.5秒で1回点滅
auto action = RepeatForever::create(blink);		// blinkを永久に繰り返す
sprite->runAction(action);

点滅を永久に繰り返すというアクションを設定します。

 

レバーも同様に設定します。

// レバーのglow処理
auto leverGlow = Sprite::create("lever_glow.png");
leverGlow->setAnchorPoint(Vec2(0.0f, 0.0f));
_lever[i]->addChild(leverGlow, 2);
// 1.5秒に1回の点滅を永久に繰り返す
leverGlow->runAction(RepeatForever::create(Blink::create(1.5f, 1)));

Cocos2d-xが使えるアクションの詳細についてはReferenceを見ると良いでしょう。

 

実行結果

ソースコードはこちら

 

10円ゲームはレトロさがウリでもあるので、ボタンやレバーのグロウ処理はレトロさを損なう結果になりますが、ボタンとしての理解度は向上したと思います。

リアリティかユーザビリティか。どちらも良いに越したことはありませんが、ゲームとしてユーザビリティを重視する場面は多いと思います。

 

次回はパーティクルを使用します。

 

]]>
http://surfrog.net/2016/08/09/cocos2dx-tutorial-11/feed/ 0
【10円ゲーム講座】第10回 効果音を鳴らす http://surfrog.net/2016/08/05/cocos2dx-tutorial-10/ http://surfrog.net/2016/08/05/cocos2dx-tutorial-10/#respond Fri, 05 Aug 2016 12:00:51 +0000 http://surfrog.net/?p=1239 Cocos2d-x

Cocos2d-x 10円ゲーム講座 第10回、効果音を鳴らします。

第9回はこちら目次はこちら

 

効果音を鳴らす

前回までの実装により、コインは転がり穴には落ちる。ゴールすれば景品も出る。しかし何か物足りませんね。何かというか、です。

コインがぶつかる音があるだけで、リアリティがまるで変わります。そんなわけで、ゲームの大切な要素、効果音を鳴らしてみましょう。

 

効果音の準備と作成

今回は効果音を作成することにしました。ネット上にフリー素材が山ほどありますが、それは使用に関してフリーなだけで大体は再配布禁止です。githubでの公開には問題があるため、自分で作ることにしました。

 

効果音を録音する(マイクで)

コインの音は簡単に録音できます。一人ではっちゃけて歌いたくなったのでこんなマイクを持っていますが、別にヘッドセットのマイクや、スマートフォンなどでも十分録音できます。

効果音の録音

コイン音は3つ録音しました。

 

  • 投入口からコインを入れた音
  • コインがレールなどに接触した音
  • コインが穴に落ちた時の音

 

 

効果音を作成する(ソフトウェアで)

ゴールした時の電子音などはBeam2002を使って作りました。Beam2002はアナログシンセ風の効果音作成ソフトウェアです。ADSRを操作するいわゆるエンベロープ・ジェネレーターのようなことができるソフトです。

レバー操作時の音と、ゴール時の音を作成しました。

  • レバー操作時の音
  • ゴール時の電子音

 

次はこれらを10円ゲームに組み込み、再生します。

 

効果音を鳴らす

効果音が用意できたので鳴らしてみることにします。Cocos2d-xで効果音の再生はCocosDenshionクラスを使用します。Denshion、でんしおん、つまりは電子音です。

 

init()で使用する効果音をプリロードしておきます。

#include <SimpleAudioEngine.h>

bool OneCoinGame::init()
{
	/*--- 略 ---*/

	// サウンドのプリロード
	CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect("se/coin_entry.wav");
	CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect("se/coin_contact.wav");
	CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect("se/coin_hole.wav");
	CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect("se/goal.wav");
	CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect("se/lever.wav");
}

CocosDenshionは拡張クラスなので、SimpleAudioEngine.hをインポートします。

 

後は効果音を鳴らしたい箇所でplayEffect()を実行するだけで、効果音を鳴らすことが出来ます。

// コイン投入ボタン
void OneCoinGame::insertCoinCallback(cocos2d::Ref* pSender)
{
	/*--- 略 ---*/

	// 効果音を鳴らす
	CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("se/coin_entry.wav");
}

これでコイン投入口をタッチした時に、お金を投入する効果音が鳴ります。

 

同じように、コインが穴に落ちた時の音、ゴール時、レバー操作時も該当箇所にコードを実装するだけです。

 

コインがどこかに接触した時の音

「コインがレールなどに接触した音」を作成しましたが、この音を鳴らすには、コインの接触を検知する必要があります。

コインの接触を検知するには、剛体が接触した時のイベントを受け取るイベントリスナーを使います。

 

接触イベントを受け取るメソッドを定義

class OneCoinGame : public cocos2d::Layer
{
public:

	// 接触イベントの検知
	bool onContactBegin(cocos2d::PhysicsContact& contact);
};

 

タッチイベントと同様に、接触イベント用のリスナーを生成して定義したonContactBeginメソッドを設定、イベントリスナーへ登録することで準備完了です。

// 衝突イベントの検知
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(OneCoinGame::onContactBegin, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);

これで剛体同士が接触する時のイベントを受け取ることができるようになりますが、接触イベントはまだ発生する設定になっていません。

接触イベントを発生させるには、各剛体に対してsetContactTestBitmask(int bitmask)でマスクの設定を行う必要があります。この値はデフォルトで0のため、0以外に設定しないと接触イベントが発生せず、イベントを受け取ることができません。

デフォルトが0なのは剛体の接触イベントは大量に検知してしまうため、必要なものだけ検知してパフォーマンスを維持するためです。

 

筐体内部

wall->getPhysicsBody()->setContactTestBitmask(0x00000001);	// 接触イベントの検知マスク

レール

rail->getPhysicsBody()->setContactTestBitmask(0x00000001);	// 接触イベントの検知マスク

コイン

coinPhysics->setContactTestBitmask(0x00000001);	// 接触イベントの検知マスク
coinPhysics->setName("coin");

接触イベントのビットマスク設定をそれぞれ設定しました。コインは接触時に識別したいのでsetName()で名前を付けて置きます。

 

ビットマスクの設定ができたら、onContactBegin(PhysicsContact& contact)で衝突を検知できるので、効果音を鳴らすコードを実装します。

// 衝突が発生した際に呼ばれるイベント
bool OneCoinGame::onContactBegin(PhysicsContact& contact)
{
	// 衝突した2つの物体について取得
	auto bodyA = contact.getShapeA()->getBody();
	auto bodyB = contact.getShapeB()->getBody();

	// 衝突した物体がコインかどうかを調べる
	if ("coin" == bodyA->getName() ||
		"coin" == bodyB->getName()) {
		// コインなら効果音を鳴らす
		CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("se/coin_contact.wav");
	}

	return true;
}

onContactBegin(PhysicsContact& contact)は、2つの物体が衝突した際に呼ばれます。

引数contactにより、衝突した2つの物体を取得することができますが、getShapeA()かgetShapeB()がコインかどうかであることと、コインが接触した場合どちらがコインかがわかりません。コインに名前を付けたのはこの判断をするためです。

名前を取得してコインなら効果音を鳴らすことで、コイン接触音を適切なタイミングで鳴らすことができるようになります。

 

実行結果

※音が小さいかもしれません。

 

ソースコードはこちら

次回はユーザビリティを向上のためにスプライトアクションを実装します。

 

]]>
http://surfrog.net/2016/08/05/cocos2dx-tutorial-10/feed/ 0
【10円ゲーム講座】第9回 はずれ穴とゴールの処理 http://surfrog.net/2016/08/02/cocos2dx-tutorial-09/ http://surfrog.net/2016/08/02/cocos2dx-tutorial-09/#respond Tue, 02 Aug 2016 12:00:06 +0000 http://surfrog.net/?p=1236 Cocos2d-x

Cocos2d-x 10円ゲーム講座 第9回、はずれ穴とゴールの処理を追加します。

第8回はこちら目次はこちら

 

はずれ穴とゴールの処理

今回ははずれ穴とゴールの処理です。

 

はずれ穴とゴールの考え方

現実の10円ゲームのはずれ穴は奥行きを持っていて、奥に10円玉が落ちることで10円ゲームの失敗となります。Cocos2d-xの物理エンジンで奥行きをもたせることは出来ないので、穴にコインが入ったかどうかをコインの位置で判定することにします。ゴールも同様です。

 

コインの位置の監視とはずれ穴、ゴールの処理

コインの位置を監視するには、Cocos2d-xのスケジュール機能を使うとフレーム毎にコインの位置を監視することができます。コインの位置の監視によってはずれ穴とゴール位置に来た事を検知します。

class OneCoinGame : public cocos2d::Layer
{
public:
	// スケジュール処理
	void update(float delta);
};

 

init()内でthis->scheduleUpdate();を実行します。

// スケジュール処理の開始
this->scheduleUpdate();

これでフレーム毎にupdate(float delta)が呼ばれるようになります。

 

続いてはupdate(float delta)の中身を実装していきます。

// 穴の矩形領域
Rect coinHole[] = {
	Rect(245, 430, 30, 30),
	Rect(67, 335, 30, 30),
	Rect(213, 335, 30, 30),
	Rect(260, 258, 30, 30),
	Rect(182, 136, 30, 30),
	Rect(61, 67, 30, 30),
};
// ゴールの矩形領域
Rect goalHole = {
	Rect(117, 67, 30, 30),
};
// フレーム毎の処理
void OneCoinGame::update(float delta)
{
	/////////////////////////////
	// コインがはずれ穴とゴールに入っている場合の処理
	// コインの速度の取得
	auto velocity = _coin->getPhysicsBody()->getVelocity();
	float speed = velocity.getDistance(Vec2::ZERO);
	// コインの速度が一定速度以下かつコインの物理が有効でかどうか
	if (speed < 3.0f && _coin->getPhysicsBody()->isEnabled()) {
		// はずれ穴に入っているかどうかの確認
		for (int i = 0; i < 6; i++) {
			if (coinHole[i].containsPoint(_coin->getPosition())) {
				// コインがはずれ穴に落ちた時の処理
				// コインの物理動作を停止し、非表示にする
				_coin->getPhysicsBody()->setEnabled(false);
				_coin->setVisible(false);
			}
		}

		// ゴールに入っているかどうかの確認
		if (goalHole.containsPoint(_coin->getPosition())) {
			// コインがゴールに到達した時の処理
			// コインの物理動作を停止し、非表示にする
			_coin->getPhysicsBody()->setEnabled(false);
			_coin->setVisible(false);

		}
	}
}

穴に触れた瞬間にコインが消えると、少し理不尽な感じが出るので、コインの速度を取得しコインの速度が遅い時だけ穴に落ちたことにします。これは実際の10円ゲームでは奥行きがあることを、2Dゲームで擬似的に表現するための処理です。コインの速度が速い時は穴を通り抜ける方が理不尽に感じないためです。

 

はずれ穴、ゴールどちらに到達してもコインは無くなることになるため、コインの物理動作を停止し非表示にします。

_coin->getPhysicsBody()->setEnabled(false);
_coin->setVisible(false);

 

ゴール時に景品を出す

ゴールの場合はクリア報酬として景品を出します。ついでなので、この景品も剛体にして物理を適用してみます。

景品

gift.png

景品。おもちゃ箱っぽいイメージです。

 

景品口の物理領域を実装。

// 景品口の物理領域
Vec2 vec[4] = {
	Vec2(202, 65),	// 左上
	Vec2(202, 23),	// 左下
	Vec2(301, 23),	// 右下
	Vec2(301, 65),	// 右上
};
auto wall = Node::create();
wall->setPhysicsBody(PhysicsBody::createEdgeChain(vec, 4, PhysicsMaterial(1.0f, 0.5f, 0.2f)));
wall->getPhysicsBody()->setDynamic(false);

this->addChild(wall);

筐体と同じように実装します。

 

続いて景品を出す処理をゴールに到達した際に追加します。

// 景品を出す処理
auto gift = Sprite::create("gift.png");
gift->setPosition(Vec2(250.0f, 74.0f));
this->addChild(gift, 1);

// 景品の物理設定
auto giftPhysics = PhysicsBody::createBox(Size(26.0f, 14.0f), PhysicsMaterial(0.6f, 0.3f, 6.0f));
giftPhysics->setMass(1.0f);			// 重さ
giftPhysics->setMoment(10.0f);		// モーメント(大きいほど回転しにくい)
gift->setPhysicsBody(giftPhysics);

景品口の物理設定を作り、少し上から景品を出現させて落とします。

 

これを実行してみると問題があることがわかります。

実行結果

10円ゲーム景品出力

景品が筐体の衝突領域に接触し、景品口に出てくれません。

 

ゲームで物理物体を扱っていると、ある物体とは衝突して欲しいけど、こっちの物体とは衝突してほしくない、といったことが出てきます。その解決方法として、Cocos2d-xでは物体にカテゴリーやマスクが設定できます。

今回は景品をコインや筐体と接触しないようにカテゴリ設定を行います。

 

物体のカテゴリ設定

剛体をカテゴライズするにはsetCategoryBitmask()を使用します。また、setContactTestBitmask()で剛体の衝突するカテゴリを指定できます。

 

コインとレールはそれぞれ衝突するようにカテゴリを指定します。

coinPhysics->setCategoryBitmask(0x00000001);	// 物体のカテゴリ
coinPhysics->setCollisionBitmask(0x00000001);	// 接触する物体のカテゴリを指定

wall->getPhysicsBody()->setCategoryBitmask(0x00000001);		// 物体のカテゴリ
wall->getPhysicsBody()->setCollisionBitmask(0x00000001);	// 接触する物体のカテゴリを指定

rail->getPhysicsBody()->setCategoryBitmask(0x00000001);		// 物体のカテゴリ
rail->getPhysicsBody()->setCollisionBitmask(0x00000001);	// 接触する物体のカテゴリを指定

コイン、レール、筐体のカテゴリを1(0x00000001)に設定し、接触する物体のカテゴリを同じく1(0x00000001)に設定します。これでコインとレール、筐体はそれぞれ接触することになります。動作としては今まで通りです。

 

次に景品の設定です。景品と景品口は接触して欲しいが、コインやレールとは接触して欲しくないので、コインやレールとは別のカテゴリである2(0x00000010)を設定します。

wall->getPhysicsBody()->setCategoryBitmask(0x00000010);		// 物体のカテゴリ
wall->getPhysicsBody()->setCollisionBitmask(0x00000010);	// 接触する物体のカテゴリを指定

giftPhysics->setCategoryBitmask(0x00000010);	// 物体のカテゴリ
giftPhysics->setCollisionBitmask(0x00000010);	// 接触する物体のカテゴリを指定

これで物体の衝突を制御できました。

 

実行結果

one-coin-game-goal-result

  • レールとコインは衝突
  • 景品は景品口と衝突
  • 景品口とレールが衝突しない

ことが確認できます。

動画

ゴールに導くのが難しくて動画撮れませんでした(笑)。内部ではテスト用のコインを作成して確認しています。

 

ソースコードはこちら

次回は効果音を鳴らすです。

]]>
http://surfrog.net/2016/08/02/cocos2dx-tutorial-09/feed/ 0