tanaka's Programming Memo

プログラミングについてのメモ。

Unity:Sceneビューのカメラでキャラを追跡と、Physicsのデバッグ表示

Unity1週間ゲームジャムの3回目「積む」に参加しました。ゲームはこちらから遊んでいただけます。是非遊んでみてください!

Unity Star Dust!

では本題です。

クリックしてユニティちゃんをジャンプさせて、音符を踏んで進んでいくというゲームなのですが、ジャンプ中にユニティちゃんが止まったり、ジャンプが途中で終わってしまうバグが発生していました。ユニティちゃんはRigidbodyの物理挙動で動かしているので、何かに衝突したことによる副作用だとは思ったのですが、観察している限りぶつかるものは見当たりません。

そこで、Colliderを見えるように設定した上で、動画キャプチャをして観察することにしました。

Colliderを表示

[Physics Debug Visualization] 機能を使って、PhysicsのColliderを見えるようにします。

Unityの[Window]メニューから[Physics Debugger]を選択します。

f:id:am1tanaka:20170626235329p:plain

Sceneビューの右下に[Physics Debug]メニューが表示されます。[Collision Geometry]にチェックを入れると、SceneビューでColliderやTriggerが表示されるようになります。

f:id:am1tanaka:20170626235433p:plain

f:id:am1tanaka:20170626235622p:plain

Sceneビューのカメラでキャラを追尾

Physics Debug VisualizationによるColliderの表示は、Sceneビューのみ有効です。スクロールするゲームなので、シーンビューのカメラがユニティちゃんを追いかけてくれないと画面から見えなくなってしまいます。

そこで、Hierarchyビューでユニティちゃんを選択したら、Sceneビュー上にマウスカーソルを移動して、[Shift]+[F]キーを押します。これで、Sceneビューはユニティちゃんを追いかけてくれます。

追尾をキャンセルする時は、他のゲームオブジェクトを選択します。

キャプチャの録画

動画キャプチャには、動画編集ソフトのおすすめ!|『Filmora 動画編集』無料ダウンロードを使いました。それほどパワーの無いPCでも、30fps程度でキャプチャできます。私は製品版を購入しましたが、無料の試用版でも変換時間に制限があったり、透かしが入りますが、今回の用途なら使えると思います。

原因判明

問題が発生した画面を観察したら、ユニティちゃんの頭の上や足元に球体のコライダーが赤く表示されることが分かりました。

f:id:am1tanaka:20170627042837p:plain

これは、音符を出現させるゲームオブジェクトに、目印代わりに追加していたSphereのColliderを削除し忘れたものでした。メッシュを非表示にしていたため、Colliderだけが残っている状況で、視覚化して初めて気づきました。

実は、最初に表示した画面のユニティちゃんの足元に、元凶の球体が表示されていました。そのときは当たり判定が表示できたことに喜んでスルーしてしまっていました。

まとめ

Physics Debuggerと[Shift]+[F]超便利!

参考URL

Unity Collaborateにアップロード(publish)できない

Unityクラウド(Cloud)のコラボ(Collaborate)にアップロードしようとすると、エラーが発生することがありました。原因は2つありました。

エラーその1

エラーが「Cannot submit change to server」の場合は、クラウドビルドが実行中かも知れません。クラウドビルドを停止してから、Publishし直せば成功します。

エラーその2

アセット名のつづりは同じで、大文字・小文字を変更した場合にエラーが発生したようでした。

  1. アセット名を変更前のものに戻す
  2. Unityを閉じる
  3. Unityを再起動
  4. [Collab]ボタンを押して、改めてPublish

以上で直りました。アップロードが成功したあとは、大文字と小文字を変更しても、うまくアップロードできるようになりました。原因は、別にあったかも知れません。ただ、上記の手順で直ったので報告しておきます。

.gitignoreをプロジェクトに追加する

2017/6/9現在、GitHub Desktopでリポジトリーを作成する際に、Git ignoreを設定したにも関わらず、ファイルが追加されないことがあります。一時的な症状とは思いますが、その際の解決策です。

.gitignoreが追加されたかどうかの確認

GitHub Desktopでプロジェクトを作成したら、[History]の最初のコミットメッセージを確認します。

f:id:am1tanaka:20170609215103p:plain

以上は成功している例です。失敗した場合、Added .gitattributesしか表示されません。その場合は、.gitignoreを生成してくれるWebサービスを使ってプロジェクト用のファイルを作成して、手動で追加します。

ここで紹介するのは、Unityの例です。それ以外のプロジェクトの場合は、Unityの部分を、そのプロジェクト(例えばVisualStudio)に置き換えてください。

設定を生成

.gitignoreファイルの内容を生成します。

  • gitignore.io - Create Useful .gitignore Files For Your Project を右クリックして、新しいウィンドウで開く
  • Unityと、Windowsと、macOSと、Linuxの4つを指定します
  • [Search・・・]という欄に、
    • Unityと入力して[Enter]キーを押し、
    • Windowsと入力して[Enter]キーを押し、
    • macOSと入力して[Enter]キーを押し、
    • linuxと入力して[Enter]キーを押します

f:id:am1tanaka:20170609231719p:plain

  • 必要な設定を追加したら、[Create]ボタンをクリックします

f:id:am1tanaka:20170609231752p:plain

  • ignoreファイルが表示されます。[Ctrl]+[A]キーを押してすべて選択して、[Ctrl]+[C]キーでコピーしておきます

f:id:am1tanaka:20170609231838p:plain

設定をテキストファイルに保存

Windowsのシステムでは、.から始まるファイルを作成できません。そこで、a.txtというテキストファイルを作成して、そこにignore設定を貼り付けた後、シェルを使ってファイル名を変更します。

プロジェクトフォルダー内にa.txtという一時的なテキストファイルを作成して、そこにコピーした内容を貼り付けます。

  • GitHub Desktopに切り替えて、プロジェクト(以下の例では、UnityGitHub)を右クリックして、[Open in Explorer]を選択して、フォルダーを開きます

f:id:am1tanaka:20170609230352p:plain

  • エクスプローラーの余白部分を右クリックして、[新規作成]>[テキスト ドキュメント]をクリックします

f:id:am1tanaka:20170609230737p:plain

  • ファイル名をa.txtに変更します

f:id:am1tanaka:20170609231935p:plain

  • 作成したa.txtをダブルクリックして、メモ帳で開きます
  • [Ctrl]+[V]キーを押して、先ほどコピーした内容を貼り付けたら、[Ctrl]+[S]キーを押して保存して、閉じます

.gitignoreファイルにリネーム

a.txt.gitignoreにリネームします。

  • GitHub Desktopに切り替えます
  • 対象のプロジェクト名(ここではUnityGitHub)を右クリックして、[Open in Git Shell]をクリックします

f:id:am1tanaka:20170609232604p:plain

  • Git Shellという端末が起動します。以下のコマンドを入力して、[Enter]キーを押します
mv a.txt .gitignore

f:id:am1tanaka:20170609232948p:plain

以上で、.gitignoreが追加できました。Git Shellは不要になりましたので、exitと入力して、[Enter]キーを押して、閉じます。

最後に

GitHub Desktopに切り替えて、[Changes]を選択してください。成功していたら、先ほどよりも対象のファイル数が減っているはずです。

f:id:am1tanaka:20170609233459p:plain

あとは、通常通り、Summaryに変更点を入力したら、Commitして、Publish、あるいはSyncしてください。

Unity1週間ゲームジャム「転がる」に参加しました

Unity 1週間ゲームジャム の第2回「テーマ:転がる」に参加しました。こんな作品↓

f:id:am1tanaka:20170530134136g:plain

マウスでティーポットを操作してマイカップにぶつけて坂道を転がして、積んであるティーカップのタワーにぶつけて崩します。ゴルフとボーリングをくっつけたようなゲームです。

プレイはこちらから。

ティーカップボーリング | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

開発の概要をちょっとご紹介。

参加目的

  • 学生さんの参加を促すための先鋒となるため
  • ゲームプログラミングとか教えているのに、ゲーム作りから遠ざかってしまったので、リハビリのため

とにかく、完成させて参加する!ということでした。

企画

専門学校の講義で紹介した、「フリーライティングによるキーワード列挙」と「ランダム選択」で一人ブレストでネタを出しました。5分で思いついたまま書きまくったキーワード(フリーライティング)から、4つのキーワードをランダムで選択して、そこに今回のテーマである「転がる」を加えた5つのキーワードを企画のスタートにしました。キーワードは以下の5つ。

  • 転がる
  • マグカップ
  • 台風
  • お堀

動作環境はWebGL縛りなので、画面サイズや操作系はそれを前提にしました。画面サイズは、1回目のゲームジャムの作品を見た感じで一先ず標準っぽかった960x540ピクセルにしました。が、もう少し小さくてもよかったように感じています。

企画案

以下のようなアイディアから始まりました。

  • クリックすると、カーソルの位置に[台風]が生じる
  • 色々なものを吹き飛ばす
  • 発生させた風の方向に加速
  • 台風の目に入れて上昇させる
  • 熊本城の地形を舞台にする?(お堀)

自分の作品は、操作の影響が狭くてダイナミックさに欠けることが多いので、ちょっとの操作で大きく動かしたい、ということを最初に考えていたのを思い出しました。この時点では台風と、転がすと、ギリギリお堀しかテーマに入っておらず、マグカップをどう消化するかを考えてました。

第2案。強引にマグカップを加えてみる。

  • [台風]で[お城]に閉じ込められた
  • お城の窓から[マグカップ]を何らかの方法で転がして操作
  • [お堀]に落ちた[鍵]をマグカップで回収して脱出する

要素は入ったけど、今度は操作が小さくなった。

第3案。

  • [台風]の中、[お堀]を探索
  • [マグカップ]に溜まった空気を吸って補給
  • [鍵]を見つけて宝物をゲット
  • 転がるがない・・・主人公が転がる生き物なら

マグカップがどうして出てくるのかが分からず、カリメロみたいにキャラクターが被ってたらどうだろうという案。マグカップアクションをするようなイメージ。普通のジャンプアクションになりそうで、規模的に無理がありそう。

そして第4案。

  • 台風だ!川沿いに住むカヤミちゃんが家に閉じ込められた。助けに行かなきゃ!
  • [マグカップ]を[転がして]、その上にカヤネズミが乗って移動
  • クリアには[鍵]が必要。何種類か出てくる。正解は不明なので全部取る
  • 雨や風を線で表現。風は時々強く吹いて障害になる
  • 地形は固定の自動生成。[箱堀]や[薬研堀][片薬研堀][水堀]など
  • 線画に近いラフな画像(黒背景に白い線)
  • マグカップは1回転に一回跳ねる
  • 操作は試して見ながら検討
    • ぼつ:マグカップを伏せると水に浮く。[お堀]を渡る(お堀は2,3キャラ分)
    • ぼつ:マグカップは、主人公のトレードマーク(カリメロの卵の帽子みたいなもの)

これが動き出した時の企画になりました。昔作成したハシルサルに近いもので、雰囲気がよさそう(特にカヤネズミ)に思いました。

しかし要素が多すぎる。出だしのキーワードは破棄して、マグカップを転がすところに集約させて、ほぼ今回の企画になりました。

企画を振り返ってみて

当初考えていたダイナミックな操作も、お気に入りのカヤネズミも残せず、最終的にティーカップを転がすという完成させやすそうな企画に落ち着かせてしまいました。

キーワード5つを全部盛り込もうとしたことも迷走の原因でした。キーワードのうちで一番強いやつでまとめた方がよさそうです。次回こそ、大きく動かして、シンプルな画面で、インパクトのある作品にしたい。

1週間を振り返る

日曜日の夜

  • テーマ「転がる」を確認
  • 企画検討で、案4まで出して寝る

月曜日

  • 企画をティーカップを転がすということに集約
  • Unityのプロジェクトを作成
  • シーン遷移の開発

コンパクトさを重視するために、余計なものを削除した結果、ゴールはティーカップタワーにして、それをティーカップを転がして倒す今の企画になりました。この時点で台風のことはすっかり忘れました。

作業は夜のみ。シーンの共有をやったことがなかったので、ほほ~と試しているうちにこの日は終わりました。

火曜日

  • 地面や背景の空を実装
  • スプライン曲線で、配列の高さを補間して、Terrain に適用

最初はマップチップで作ろうとしていましたが、適したマップタイルの素材を見つけることができませんでした。アセットストアを眺めていたら Nature Starter Kit2 が目に留まって、地面は Terrain にしちゃおうということになりました。

Terrainエディターで面を作るのは厳しそうだったので、高さの配列データから滑らかな地面を生成するコードを作って、この日は終了。ちょっとお金払えばUnityストアにアセットがあったのですが、勉強ということで自作しました。

PostProcessingStackを組み込んで、この頃は画面が光ってました。

水曜日

  • ティーポットのモデルを探して、転がすゲームオブジェクトを作成
  • 仮のパワーゲージを作成して、カップを転がす
  • ミニマップの表示
  • ルールの明文化

専門学校の出講日で、午前は一年生向けの講義なので開発できず。午後の2年生の時間に、Unity1週間ゲームジャムに参加しようよと言っていたので、作業時間にしました。何かしらみなさん作り始めておりましたが、結果ははてさて。

この頃は、転がす強さをパワーゲージ上でクリックして、好きな強さで確実に転がせる操作を検討していました。英国紳士がクリケットのラケットみたいなのを振り回して、カップを転がすイメージ。

当初の目論見では、この日にはゲームを動かしておく予定だったのですが、全然でした・・・

木曜日

  • シーンやフェーズの遷移によるゲームの初期化など
  • カメラや操作説明を画面に表示
  • 転がす操作を、パワーゲージからティーポットで弾くことに変更
  • カップのタワーを作成して画面に配置
  • WebGLにビルド

ようやくこの日にカップタワーが入って、カップを転がして倒すことができました。崩すのが面白いことが確認できて一安心した一方、WebGLでの動作がえらく遅くなり困ったことに。ポリゴン数を確認したところ、16M三角ポリゴンとか恐ろしい数字が出ていました。これは減らさねばと思いつつ、ツールがないのでこの日は終了。

金曜日

  • ポリゴン減らし
  • ティーポットの操作の実装
  • 吹き出しや、ティーカップのタワーをステージデータから自動生成するように

午後に1年生向けの講義をして、放課後は居残って作業です。ポリゴンをいじるチャンスはこの日しかなかったので、3dsMaxの操作を調べながら、プロオプティマイザーとやらで減らせるのか、というレベルからなんとかローポリデータの作成をしました。最終的に、ティーポットは5万ポリゴン、ティーカップは2万ポリゴンほどに。十分多い気がしますが、これ以上減らすと形が崩れ、手元の環境では処理落ちは改善していたので、これでいくことにしました。

maxで見ると法線が今一つであれこれ試していたのですが、Unityに読み込んでみたら大して目立ちませんでした。調整しながらUnityで見ないと。

土曜日

  • 最低限のゲームルールの実装
  • 残りカップ数やスコアなどのインターフェース追加
  • WebGLの処理速度対策

ステージ作成にはこの日も入れず。ポリゴンの削減、空のカメラの廃止、PostProcessingStackの無効化で、WebGLでの動きが滑らかにできて、時間はギリギリながら光明は見えました。あと1日・・・

日曜日

  • Tiledでステージを作成して、読み込み
  • 効果音の組み込み
  • パーティクルの実装
  • 完成

最終日にして、ようやくステージデータに取り掛かりました。が、この段階ではツールはなし。手入力はきついだろうと思い、先日知った Tiled を使うことにしました。やりたいことはシンプルだったので、データを作成して、あとはデータの読み込み。

Tiled の保存形式は XML なので、 C# の XMLDocument を使えば簡単に読み込めました。あれこれやってステージデータをゲームに組み込めるようになったのは15時すぎ。締切まであと5時間。

2面ほど作って遊びながら、目立った不具合を潰し終えたのが17時過ぎ。軽食を食べながら効果音を探してみたところ、必要そうなものが一通り揃ったので効果音を入れることに。これは SoundSource の PlayOneShot であっという間に入りました。Unity の凄み!

あとはステージを作っては遊び、作っては遊びで、19時すぎに7面までできました。30分ほど、残っている作業を優先順位に従って潰していって、残り30分で一度アップロードして公開設定。

残り時間でパーティクルを入れて、微調整して、リビルドしている間にタイムアップ!

お疲れ様でした。・・・と思ったのですが、締め切り後も更新できるとのことでしたので、もう少し細かい調整を加えてアップし直しました。

怒涛の一週間が終わりました。

開発中に感じたこと

正直、1週間で時間が足りなくなるとは思っていませんでした。ブランクの影響は大きかったです。他の方の開発日誌を見ていると、2,3日で形にしている方が多い印象だったので、やはり時間がかかりすぎでした。

必要なものがいくつか見えたので、それを整理しておいて、初日からプロトタイプに取り掛かれるようにするのが次回までの宿題です。そして、他の方がやっているみたいに、開発の進捗をツイートしたいものです。

その他、箇条書きで。

  • シーン管理の手順を決めて、必要なコードを用意する
  • Tiledのマップデータを読み込めるようにする
  • 簡単な3Dモデルは自作できるようにする
  • 画像素材は自分で1枚に統合せず、バラバラのものをUnityにパッケージさせる
  • フォントを見つけておく
  • 使えそうなアセットを研究
  • 手書きのイメージが全く作れなかった。日頃から落書きして、描くことに慣れておく
  • 手軽にプレイ動画をGIFに変換できる環境の調査
    • UnityのFrame Captureというプラグインがあったけど、うちのPCでは能力不足か、フレームレートが出ず
    • フレームレートが遅くていいなら、Screenpressoが楽
    • Screenpressoのキャプチャが遅いのも、うちのPCのせいかも・・・
  • ツイートとランキングは最初から組み込んでおく

技術的なこと

今回、以下のようなことをやりました。

  • マルチシーンを使って、ベースのシーンに、タイトルやゲームオーバー、クリアを重ねて制御
  • ScriptableObjectとポリモーフィズムを使ったシーンやフェーズの管理
  • 複数のカメラを使ってミニマップの表示
    • 大昔、Unity3の時代に知ったチュートリアルの手法でやりました。今はカメラにRenderingTextureにレンダリングさせる方がよかったでしょうけど、細かい調整方法で時間を食いそうだったので、知っている方で対応
    • 公式のチュートリアルに丁度この内容が出たようです
  • Terrainの自動生成
    • Terrainエディターでステージを作るのはしんどそうだったので、16個の高さデータを渡して、スプラインで補間した高さをTerrainに組み込みました
    • これのおかげで、残り時間が少ない中で、複数のステージをバランス調整しながら用意できました
    • 補間につかったスプラインのアルゴリズムが今回の用途には適しておらず、余分なうねりが出てしまいました。他の方法を検討したいところ
  • Tiledの読み込み
    • フリーのマップエディターのTiledのtmxファイルから必要な箇所だけ読み込む処理を作りました
    • XMLなので、C#のXMLDocumentを利用すれば技術的には楽勝でした(しかし調べるのに時間がかかった)
    • WebGLだとファイルの読み込みができないようで、Inspectorにstringフィールドを表示して、無理やり突っ込みました
      • 手作業が少し必要で、容量に制約があるようなので要改善
  • 3dsMaxでのポリゴン数の削減
    • インターネットからダウンロードしたティーカップやティーポットのテクスチャー数が膨大だったので,3dsMaxのプロオプティマイザーでポリゴン数を減らしました
    • オブジェクトを選択して、モデファイヤからプロオプティマイザーを選択して、[計算]ボタンを押したあと、ポリゴン数かポリゴンのパーセントを入力して、他の項目に移動すると摘要されます

利用したアセットやツール

この作品の開発でお世話になったアセットやツールのご紹介。

Shapes. Nature Starter Kit 2

f:id:am1tanaka:20170529200242p:plain

これは美しい!と思ったのを覚えていて、Terrainのテクスチャや草、木に利用しました。が、これ、ポストエフェクトで綺麗にしてるんですね。WebGLでもそこそこ動くとはいえ、今回はフレームレートを高くしたかったので、ポストエフェクト切ってしまいました・・・。結果的に、PS1というか、昔の3Dゲームっぽい画面に・・・

G.E.TeamDev. 2D Sky FREE

f:id:am1tanaka:20170529201125p:plain

スカイボックスの空を調整しきれなかったので、2Dだし、2Dっぽい空をということで選びました。とても綺麗なのですが、良く見ると雲が切れてたり、カメラを動かすとおかしくなったり、少々癖があります。有料版もあるので、そっちならうまく動くのかな?

空専用のカメラを用意して、それを背景に重ねていい具合で動くようになったのですが、フレームレートが落ちてしまいました。ということで、静止画として背景に貼り付ける利用方法となりました。

Tothetapp. Cup 3D Model

archive3d.net

ティーカップのモデルとして利用しました。ティーカップだけだと思っていたらティーポットもついていて、これで弾けばいいやとなって、英国紳士がラケットでカップを転がす案は消えました。

インテリアデザインなどのレンダリング用で、いわゆるハイポリ。100万ポリゴンを軽く越えていたので、3dsMaxのプロオプティマイザーでポリゴンを減らしたものを使いました。

魔王魂

音素材は、エンディング曲以外は魔王魂さんのフリー効果音素材で探しました。時間が少ない中で、一通りのものが見つけられたので大助かりでした。あちこちのゲーム制作ブログでお名前を拝見していたので、真っ先に探しに行きました。

H/MIX GALLARY

H/MIX GALLARYさんのジングル「祝福された大地」がエンディングにぴったりだったので使わせていただきました。クリアしなくても聞けますが、クリアして聴く一曲はお風呂上りのビールのように一味違う気がします。

Ishida So. 簡略化した3次スプライン曲線の生成方法

地面の高さデータから滑らかな Terrain データに補間するためのアルゴリズムはこのサイトで勉強しました。

利用したツール

  • Unity5.6
    • これがないと今回のゲームジャムは始まりません。これが十分動かせるPCを持っていることが前提ですが、ゲームを作るのには最高の開発ツールの一つだと思っています
  • Visual Studio 2017 Community
    • Unity5.6にバンドルされているバージョンです。2015は起動が遅く、MonoDevelopを使っていましたが、2017はどうだろうと思って使ってみました。補完機能が秀逸で、起動も以前のような遅さは感じません。個人利用はこっちに乗り換えようと思います
  • Tiled
    • フリーのマップエディターです。使いやすく、保存形式もXML形式で分かり易いです。ダウンロード時に$9必要な雰囲気ですが、その上のリンクで無料で入手できます。本当に優れたツールなので、自分は支払います
  • Photoshop CS2
    • ロゴ作成や、インターフェース作りに使いました。古いのを未だに使ってますが、ウィンドウの優先順位が崩れたりして、そろそろ限界な感じです・・・
  • Screenpresso
    • スクリーンキャプチャソフトです。動画を撮影したり、スクリーンショットの撮影に利用しました。これも無料で使えますが、制限がない方が楽なのでライセンス購入しています
  • 3dsMax
    • ティーセットのポリゴンを減らすのに使いました

最後に

とにかく、完成して、公開できてよかった!

リハビリの目的は強烈に達せました。頭の筋肉痛が出ております。

思った通りの注目や評価を得られず、がっかりした人もいるかも知れません。特に発表直後は疲れていて、落ち込んでしまいがちです。まず、ご飯食べ得て、良く寝て、回復させてください。コンテストではないし、仕事でやっている訳でもありませんし、自分が考えたものが完成して、発表できただけでも大成功だと思います。また、ネットでは発見されるまでに時間がかかります。半年後に突然注目されるとかもあるので、焦らず、コツコツ継続するのが吉です。

残念ながら未完成に終わったとしても、次回また挑戦したら今度は出来るかも知れません。まずは鋭気を養い、その後、ああしたい、こうした方がよかった、と気付いたことがあれば、次回はそれを実現できるように調査すればいいのだと思います。・・・と、自分にも言い聞かせてます。

さて、最初の目的であった、学生さん達は発表できたのか。水曜日のお楽しみです。

末筆ながら、素晴らしいサイトを作って、イベントを開催してくださいました naichilab. さん、ありがとうございました。

Phaserをサンドボックスで試す

f:id:am1tanaka:20170419210146p:plain

HTML5ゲームエンジンPhaserのチュートリアルを実装する記事です。Phaserのサンドボックスを使うので、最新のWebブラウザーが動くインターネットに接続された環境で、インストール作業をせずに試すことができます。

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

am1tanaka.hatenablog.com

Phaserをサンドボックスで試す(7)文字の表示とスコアの実装

f:id:am1tanaka:20170417231648p:plain

前へ

仕上げに、文字を表示して、スコアを実装します。Phaser公式チュートリアルMaking your first Phaser game: Part 8 - Finishing touches - Learn - Phaserを参考にして進めます。

(6)星を作成するの続きです。

先のサンドボックスを閉じてしまっていたら、こちらを右クリックして[新しいウィンドウで開く]で開いて、作業を始めてください。

スコアの定義と文字の表示

createタブを開いて、以下の場所に必要な変数を定義します。

f:id:am1tanaka:20170418180948p:plain

追加するコードは以下の通りです。

// 9:
// (A Valiable of the score)
var score = 0;
// (A Valiable of the Text)
var scoreText;

文字を表示するテキストを作成して、変数scoreTextに代入します。一番上に表示したいので、function create() {の最後に追加します。

f:id:am1tanaka:20170418181137p:plain

追加するのは以下のコードです。

    // 86:
    scoreText = game.add.text(12, 12, 'Score: 0', { font: "24px", fill: "#000" });

左から12ピクセル、上から12ピクセルの座標に、Score: 0と表示するテキストを作成して、変数scoreTextに代入します。フォントサイズは24ピクセル、黒で塗りつぶします。

PLAYタブに切り替えて画面を確認してください。文字が表示されます。

f:id:am1tanaka:20170417223847p:plain

スコアを加算する

星を取った時に、点数が10点入るようにします。どこにプログラムを書き足せばよいでしょうか?

星を取った時に、星を消すコードを前の記事で書きました。その場所にスコアを10点増やすコードを追加すれば、目的を達することができそうです。

updateタブを開いて、関数collectStar内の以下の場所に、点数を加算するコードを追加します。

f:id:am1tanaka:20170418181400p:plain

追加するコードは以下の通りです。

    // 44:
    //  Add and update the score
    score += 10;
    scoreText.text = 'Score: ' + score; 

PLAYタブに切り替えたら、星を集めてください。点数が加算されます。

f:id:am1tanaka:20170417231648p:plain

コードを書く場所を工夫することで、自動的に「星をとった時」に点数を加算することができました。プログラミングは、「どこに」「どのような順番で」コードを書くかによって、同じコードでも意味が変わることがあるのです。

ここまでのまとめ

このチュートリアルは、これで完成です。利用する画像の指定の仕方、画像やパターンを持ったスプライトの読み込み、グループの作成、スプライトの表示、物理エンジンの活用、キー操作方法、キャラクターが重なった時の処理、文字の表示方法など、多くのことを実装してきました。これを応用すれば、もっと色々なことができるでしょう。例えば、クリアやゲームオーバー要素がありません。星と同様の方法で障害物を作成して、プレイヤーと重なったらプレイヤーを削除するようにすればゲームオーバーが作れます。あるいは、ゲームオーバー要素はなくして、以下に短い時間で星を全て集められるかを競うようにすることも考えられます。発想を広げるための画像が http://examples.phaser.io/assets/ に用意されています。

ここで示したチュートリアル以外にも、コミュニティーで作成された700を越えるチュートリアル(Tutorial - Learn - Phaser)や、公式チュートリアル(Official Phaser Tutorials - Learn - Phaser)が公式サイトで公開されています。自分が作りたいゲームに近いものを探したり、似た処理をしているサンプルを探して、どのようにプログラムが作られているかを知ることができます。

Phaser Forumに疑問や質問を書き込めば、コミュニティーの人たちが助けてくれるかも知れませんので活用してみてください(英語ですが)。

完成版

以下、完成版のサンドボックスプロジェクトです。

完成版

最後に

Phaserで思い通りにゲームを作るには、JavaScriptというプログラミング言語の理解が必要になります。基礎を独学で学べる便利なサービスがありますので紹介します。

Phaserは安価なPCでも動かすことができる、モダンなゲームエンジンです。英語の情報が多いですが、サンプルのプログラムは沢山ありますので、プログラムを見て勉強することができるでしょう。

前へ

参考URL

Phaserをサンドボックスで試す(6)星を作成する

f:id:am1tanaka:20170417221324p:plain

前へ | 次へ

プレイヤーが集める星を作ります。Phaser公式チュートリアルMaking your first Phaser game: Part 7 - Starshine - Learn - Phaserを参考にして進めます。

(5)プレイヤーの操作の続きです。

先のサンドボックスを閉じてしまっていたら、こちらを右クリックして[新しいウィンドウで開く]で開いて、作業を始めてください。

星を登場させる

プレイヤーが集めるべきアイテムの星を作ります。星は複数登場して、プレイヤーとの接触を物理エンジンに委ねます。プレイヤーと地面を衝突させる時を思い出してください。衝突させる時に、 game.physics.arcade.collide(player, platforms); として、衝突する対象を指示しました。星を個別に作成した場合、全ての星に対してこの指定をしなければならず面倒です。そこで、地面の時と同じく、新しくstarsというグループを作成して、そこに星を登録していくことにしましょう。

createタブを開いて、まずは以下の場所にstarsを定義します。

f:id:am1tanaka:20170418174449p:plain

追加するコードは以下の通りです。

// 7:
// (A valiable of the group contains the stars)
var stars;

function create() {に星のグループを作成して、星を作成しながら物理エンジンなどの設定をします。以下の場所です。

f:id:am1tanaka:20170418174756p:plain

追加するのは以下のコードです。

    // 65:
    stars = game.add.group();

    stars.enableBody = true;

    //  Here we'll create 12 of them evenly spaced apart
    for (let i = 0; i < 12; i++)
    {
        //  Create a star inside of the 'stars' group
        let star = stars.create(i * 50, 0, 'star');

        //  Let gravity do its thing
        star.body.gravity.y = 6;

        //  This just gives each star a slightly random bounce value
        star.body.bounce.y = 0.7 + Math.random() * 0.2;
    }

PLAYタブに切り替えて動きを見てください。星が作成されて落下をします。ただ、床は通り抜け、プレイヤーで取ろうとしても取れません。

f:id:am1tanaka:20170417210700p:plain

コードの意味

// 8:
var stars;

すでに何回か似たようなコードが出ていますね。これでstarsという名前の変数を定義しています。これに、作成した星のグループを代入して利用します。

    // 65:
    stars = game.add.group();

    stars.enableBody = true;

65行目で、グループを作成して、変数starsに代入しています。67行目で、星グループの物理エンジンを有効にしています。地面と同じ設定です。

    // 70:
    for (let i = 0; i < 12; i++)
    {

これはfor文という構文で、プログラムを繰り返すのに使います。細かい意味は後回しにして、一先ずここでは以下のことを確認しておいてください。

  • ローカル変数i
  • 0から1ずつ増えながら
  • 11になるまで
  • {}の間のコードを繰り返します

つまり、iが0~11まで変化しながら、{}の間を12回繰り返し処理されます。

        // 73:
        let star = stars.create(i * 50, 0, 'star');

星のグループに、X座標は現在のiに50を掛けた場所、Y座標は最上段に、starの名前のグラフィックを作成して、そのインスタンスをローカル変数starに代入します。iは繰り返すごとに、0 > 1 > 2 > … > 11 と変化していきますので、X座標が 0 > 50 > 100 > 150 > … と、50ピクセルごとに並ぶことになります。

        // 76:
        star.body.gravity.y = 6;

星に重力加速度を設定します。1秒で6ピクセル/秒加速するように重力落下させます。

        // 79:
        star.body.bounce.y = 0.7 + Math.random() * 0.2;

星のY方向の弾性係数を設定します。Math.random()は、乱数を生成するためのコードで、0以上1未満の範囲の乱数を返します。0以上1未満の乱数に0.2を掛けた値を0.7に足していますので、0.7以上0.9未満の弾性係数を設定しています。

今はまだ跳ね返らないので画面外まで星が落ちてしまいますが、跳ね返りを設定すれば、星ごとに少し異なる高さで跳ね返るはずです。作業を進めて、予想が合っていたかを確認することも大切な作業です。

星と地面を衝突させる

星と地面を衝突させるコードを追加します。これはプレイヤーと地面に当たり判定を付けた時と同じメソッドを利用して、パラメータを星のグループと地面のグループにします。

updateタブに切り替えて、以下の場所にコードを追加します。

f:id:am1tanaka:20170418175442p:plain

追加するコードは以下の通りです。

    // 5:
    game.physics.arcade.collide(stars, platforms);

これで星が地面で跳ね返ります。PLAYタブに切り替えて確認してください。

f:id:am1tanaka:20170417213658p:plain

予想通り、星が異なる高さで跳ね返ります。

星を取れるようにする

プレイヤーと星グループの重なりを確認して、重なっていたらその星を消すようにします。地面の時は、接触したかと、どこと接触したかを確認すればよかったですが、今回はどの星と接触したかを把握する必要があります。そのために新しい構文を使います。

updateタブに切り替えたら、以下の場所にコードを追加します。

f:id:am1tanaka:20170418175645p:plain

追加するのは以下のコードです。

    // 6:
    game.physics.arcade.overlap(player, stars, collectStar, null, this);

playerstarsグループが重なる(overlap)かを確認して、重なっていたらcollectStar関数を呼び出します。重なった時の追加的なチェックはせず(null)、collectStar関数はthisから実行します。

collectStar関数が必要になりましたので、updateタブの最後に追加します。これまでと違って、最後の}の下に追加するので注意してください。

f:id:am1tanaka:20170418180114p:plain

追加するコードは以下の通りです。

    // 39:
function collectStar(player, star) {

    // Removes the star from the screen
    star.kill();    

}

関数collectStarを定義しています。プレイヤーと星グループ内の星のどれかが接触した時に、Phaserが自動的に呼び出してくれます。このような関数をコールバック関数と呼びます。collectStar関数は2つ引数を取ります。overlap関数の接触対象に並べた順番で、接触したオブジェクトのインスタンスを渡してくれます。

42行目のstar.kill();は、starを星グループから削除するコードです。starは引数で受け取ったものですので、プレイヤーと重なった星がこれで画面から消えます。

PLAYタブに切り替えて操作します。星を集めることができるようになりました。

f:id:am1tanaka:20170417221324p:plain

まとめ

地面を作成した時と同じような手順で星のグループを作成して、星を作成しました。星を12個登場させるために、繰り返し文forを利用しました。物理エンジンの振る舞いを設定した上で、地面との接触、プレイヤーとの接触を有効にして、プレイヤーと重なった星を消す処理を実装しました。

ここまで実装したサンドボックスは以下で確認できます。

(6)のサンドボックス

以上で、このチュートリアルでのゲームの動きは完成です。最後の仕上げに、文字を表示して、スコアを実装します。

前へ | 次へ

参考URL