みこしの活動日記

みこしの日々の活動を記録していきます。

初スマホゲームリリース! ~鬼ハ追イカケ君ハ逃ゲル~

Android, iOS向けに「鬼ハ追イカケ君ハ逃ゲル」というゲームをリリースしました。

人生で初めて作ったスマホゲームです。

ぜひ遊んでみてくださいね!

ストアのURL



f:id:quietMikoshi:20200902015215p:plain



PV
www.youtube.com



プレイ動画
youtu.be



GitHubリポジトリ
github.com

レビュー記事を掲載していただいたサイト

スマホゲームCH様

gameappch.com

本ゲームの概要

f:id:quietMikoshi:20200904182701p:plain:w600 あなたは密閉空間に閉じ込められたプレイヤーです。

辺りには不気味な雰囲気が漂っています...

密閉空間の中ではあなたを狙って鬼たちがうごめいています。

ここから脱出できますか...?

ルール

f:id:quietMikoshi:20200904182628p:plain:w600 プレイヤーはステージ内のどこかにある脱出口から脱出できたら、ステージクリアです。

プレイヤーの初期位置と脱出口の位置はステージによってバラバラです。

f:id:quietMikoshi:20200904182446p:plain:w600
f:id:quietMikoshi:20200904182646p:plain:w600 脱出口にたどり着くまでに、橋や壁といったアイテムをうまく使わなければいけません。

f:id:quietMikoshi:20200904182610p:plain:w600 さらに、追ってくる鬼から逃げなければいけません。

鬼に触れたらゲームオーバー!

ステージ2階で橋を設置すればブロック間を行き来できるようになり、ステージ1階で壁を設置すれば鬼の通行を阻止できます。

面白いところ

脱出口を探す楽しみ

脱出口の位置はコースによってバラバラなので、コースごとに探索する必要があります。

現在位置と脱出口までの距離を頼りにコース内を探索するのは、ワクワクします!

鬼が追ってくる怖さ

鬼はプレイヤーを見つけるとズン、ズンと追ってきます。

鬼に触られたらゲームオーバーだ。急いで逃げなきゃ!😣

鬼がどこからやって来るか分からないハラハラドキドキ感、鬼がいきなり現れたときの驚きがたまりません!

アイテムの駆使

コースによっては橋、壁という2種類のアイテムを駆使しないと、クリアできないものもあります。

地形や鬼の位置に合わせて、上手にアイテムを使って脱出口へ向かいましょう!

最後に

f:id:quietMikoshi:20200904182518p:plain

プライバシーポリシー ~鬼ハ追イカケ君ハ逃ゲル~

広告について

本アプリではAdMob(Google Inc.)を広告に使用しており、AdMobがユーザーの情報を自動取得する場合があります。取得する情報、利用目的、第三者への提供等については、以下の広告配信事業者のアプリケーション・プライバシーポリシーのリンクよりご確認ください。 Google 広告に関するポリシー https://policies.google.com/technologies/ads?hl=ja

ネットワークについて

本アプリでは、広告表示のためネットワークへのアクセスが利用されます。

問い合わせ先

不具合やご不明な点などございましたら下記にご連絡ください。 astronomer.3player@gmail.com

VR技術者認定試験(セオリーコース)に合格しました

7/13に受験したVR技術者認定試験(セオリーコース)に合格しました!  

大学の研究室でVRの研究をしたくて、VRについての知識をつけようと思い受験しました。 

今回は、合格に至った勉強法について紹介したいと思います。 

VR技術者認定試験には指定の教科書と過去問があります。この二つさえあれば他に何も必要ありません。 

まず指定の教科書がこちら。

www.amazon.co.jp

日本バーチャルリアリティ学会が出している「バーチャルリアリティ」という書籍です。 

次に、過去問とその模範解答は

vrsj.org

に置いてあります。VR技術者認定試験のホームページです。 

さて勉強に必要なものがそろったので、次に勉強法について説明します。 

まず試験範囲になっている章(セオリーコースだったら1~4章)を一度でいいのでざっと目を通します。真面目に読まなくて大丈夫です。 

そして、早速過去問に取り掛かります。過去問を印刷してその紙に赤ペンで答えやメモを書き込んでいき、赤い下敷きで隠して暗記していくのが私のおすすめです。最初のうちは全然分からない問題ばかりだと思うので、とりあえず印刷した紙に模範解答を全部書き込みます。 

7割くらいの問題は、教科書のどこかから一字一句違わず抜き出して作ってあります。残りの問題もかなり似た文章が教科書のどこかに必ずあります。ですので、印刷した問題の近くに「何ページに書いてある」というメモをすべての問題に対して書いておけば、後で見返した時にスムーズに暗記がはかどります!選択肢の正誤問題だったら、この文章のここがこういう風に間違っているというところまで書いておけば万全です。 

知識がそこそこたまってきたら、模範解答を見ないで解いてみるとよいでしょう。   

この方法で過去問5年分行えば十分です。私は5年分やって合格点を余裕をもって上回れました。5年分も行うのはだるい!と思っても、被っている問題も散見されるので実際のところ5年分の労力は必要ありません。 

以上です!上級バーチャルリアリティ技術者になりたいので、アプリケーションコースの方もがんばって勉強したいと思います!

POV-Rayで月見のシーンを描いてみた

POV-Rayという3Dレンダリングソフトがあるのですが、今回POV-Rayを使って月見のシーンを描いてみました。

f:id:quietMikoshi:20190527161209j:plain

POV-Rayでは3Dのオブジェクトを一つ一つプログラムで書いていくという形式になっています。ソースコードを以下に載せて解説していきたいと思います。

それではオブジェクトを一つ一つ見ていきます。

月は球体に月のテクスチャを貼っただけです。以下が貼ったテクスチャです。

星空

星空は http://www.oocities.org/ccolefax/galaxy.html にあるGALAXY.ZIPに梱包されているGALAXY.SFというファイルを拝借して描きました。34行目にあるstar_countという変数の値を変えることで星の数を調整できます。

地面

地面はススキに隠れてほとんど見えていませんが、地面もxz平面に土のテクスチャを貼っただけです。以下がそのテクスチャです

縁側

表面にtextures.incで定義済みの木のテクスチャを貼った超楕円体です。

月見団子とそれを乗せる台

月見団子とその台はunionにして一体にしてあります。これは最終的に位置、大きさ、回転を微調整する際にまとめて調整できるようにするためです。まず月見団子は球体を並べているだけです。規則正しく並べたかったので、while文で一気に描いています。次に台ですが、台は月見団子が接する上部と穴が開いている下部のunionです。上部は皿のような形にしたかったので、超楕円体の中をそれより少しだけ小さな超楕円体でdifferenceでくりぬいたあとに、さらにdifferenceで上部を切断して消しています。下部は超楕円体と2本の円柱とのdifferenceでくりぬいてあります。

ススキ

ススキは茎と穂のunionでできています。

ススキ1本

ススキの茎には根元から上がっていくにつれて緑から黄色になっていくようにグラデーションがついていますが、RGBベクトルを変化させながら球体を直線状に動かしてできています。これをスイープ効果といいます。続いて穂ですが、穂に一番力を入れて作りました!

上がススキの穂の作り方ですが、穂は円弧の集合でできています。左下に茎の先端と書いてありますが、茎と穂の連結部分のことです。茎の先端を中心とした同心円を考えます。黒い実線が実際に描いた穂ですが、円の半径が小さなうちは円弧の中心角を大きめにし、半径が大きくなっていくにしたがって中心角を小さくしていきます。そして何本かできた穂を青い点が茎の先端に来るように全部移動させます。

ススキを1本作ったところで、あとはこれを量産すればススキ畑になります。x,z軸方向にwhileの2重ループを使って長方形の畑を作ります。このままだとススキがすべて同じ方向を向いてしまうので、乱数を発生させるrandという関数を用いてランダムにy軸まわりに回転させています。

光源

光源はカメラから見て月の少しだけ手前の位置に一つとカメラの後ろ側にもう一つ置いてあります。本当は月と同じ座標に光源を置きたかったのですが、そうすると月の球面の内側に光源を置くことになり光が外側に届かなくなってしまうので、月の少し手前に置くということにしました。また、月の光源一つだけだと月見団子の後ろ側などが暗くなりすぎてしまうので、カメラの後ろ側にも暗めの光源を置きました。                           

以上になります。Blenderで3Dモデリングをした経験はありましたが、プログラムを書いてモデリングしたのは初めてでした。いい経験になりました。

Pythonで「令和」を描きました

さてGWも折り返しましたが、皆さんはどうお過ごしでしょうか? 

私はというと毎日おうちに引きこもっているだけです。時間がたっぷりあったし、元号が変わったということで適当にPython3のmatplotlibで「令和」を描いてみました。 

ただそれだけの記事です… 

f:id:quietMikoshi:20190503092906p:plain 

 

線分をつなげただけの単純な構造になっています。

パルテナの鏡というゲームがありまして…

f:id:quietMikoshi:20190313190506j:plain 

ちょっと前のゲームですが、3DSのゲームに「パルテナの鏡」というゲームがあります。

個人的に、3DSのゲームの中でこのパルテナの鏡が一番です。3DSの本格的なFPSゲームだと思っています。

このゲームには一人用プレイとインターネット対戦があります。一人用では敵を倒しながらストーリーを進めていきます。やりこみ要素が十分にあって、一人用もめっちゃ楽しいです。 

ですが私がドはまりしたのがインターネット対戦です。ステージ上に何人かのプレイヤーが放たれてバトルする(PUBG要素はありますが、やられても復活できます)んですが、このゲームの真に面白いのは武器のスキル構成を自分でいかようにも変えられるところです。時間をかければ強い武器を作れて敵を蹂躙できるので、私が高校生のころはかなり武器のスペックを研究したときもありました(;^ω^)余談ですが、スーパーアーマーを付与してから近接武器で敵をひたすら脳筋のように殴りに行くのが、たまらなく楽しかったです。中毒になってましたね。  

私の大好きなパルテナの鏡3DS以降は続編が出ていません。パルテナの鏡の制作を手掛けた任天堂の桜井さん曰く、続編はないらしいです…ここまで完成度の高いゲームで「続編が出てほしい!」という声も聞くので、続編を作らないのは残念です…パルテナの鏡が私の青春の一部だったのになぁ(´Д`) 

このゲーム、今ならBookOffで2000円くらいで買えます。シューティングゲームが好きな人ならまず面白いと思いますよ!良かったらプレイしてみてはいかがでしょうか? 

リメイク版とかでもいいから続編出てくれないかな…青春を取り戻したい。。。

【Unity】ソースコード解説 "Touch The Balls!"

f:id:quietMikoshi:20190307231528p:plain
"Touch The Balls!"のアイコン

unityroom.com

私が初めてUnityで作った3Dゲーム「Touch The Balls!」の解説記事を書いていこうと思います。上にリンクを貼ってありますので、良かったら遊んでみてください!(PCでの起動をおすすめします) 

ソースコードの構成は

  • ゲーム全体を統括する(GameManager.cs)

  • Stage1~5のギミックを決めるのにそれぞれ1つずつ(Gimmick1~5.cs)

  • プレイヤ、ボールーの挙動を決める(PlayerController.cs, PointBallController.cs)

  • 触れると吹き飛ばされる敵、動く床・壁の実装(EnemyController.cs, FloorController.cs, RefrectorController.cs)

  • タイトル画面から各ステージへシーンを遷移する(ChangeScene.cs)

の合計12本となっています。ソースコードはすべてC#で書いてあります。

   

GameManager.cs  

ではまずゲーム全体を統括するGameManager.csを見ていきます。

9行目はテキスト、10行目は効果音のゲームオブジェクトをpublicで格納するための変数を宣言しています。

f:id:quietMikoshi:20190304111350p:plain
GameManager

そして上図のようにGameManagerのインスペクター画面からアセットを入れます。

12~17行目はGameManager.csのソースコード内でのみ使う変数をprivateで宣言しています。17行目のAudioSource型の変数は10行目で格納した音源を鳴らすときに使います。13,14行目の変数にstaticをつけているのは他のクラスからもアクセスできるようにしておくためです。 

続いてStartメソッドの中に入っていきます。Startメソッドでは初期化を行います。

20行目でflagをfalseにしているのはステージ上のギミックがまだ作動しないようにしておくためです。ゲーム開始直後にカウントダウンが始まるようにしているのですが、カウントダウンが終了してからflagをtrueにしてギミックが作動するようにします。

21行目は"CountdownCoroutine"という名前のコルーチンを始めるという指示です。コルーチンが始まるとUnity内の他の処理が一旦停止し、コルーチン内の動作が全て終了したのちに再びUnityが動き始めます。コルーチンを使って他の動作をいったん止めてカウントダウンを行います。さて93~114行目にCountdownCoroutineメソッドがあります。 

まず94行目でSetActiveメソッドを使ってCountdowntextをtrueにしています。カウントダウンを表示するためのテキストは、普段は非アクティブしておいてカウントダウンを行う時だけアクティブにします。96~109行目の流れは 

"3"を表示→1秒待つ→効果音を鳴らしながら"2"を表示→1秒待つ→効果音を鳴らしながら"1"を表示→1秒待つ→効果音を鳴らしながら"GO"を表示→1秒待つ 

となっています。PlayOneShotメソッドは引数にとった音を一回だけ鳴らします。また、yield returnでコルーチンをいったん中断し1秒間待つ処理を挟んでいます。 

最後に111,112行目でカウントダウンのテキストを空白・非アクティブにしてコルーチンは終了です。 

コルーチンが終了するとStartメソッドに戻ります。26行目のInvokeメソッドは第2引数で指定した秒数後に第1引数で指定したメソッドを実行するメソッドです。88~90行目にMoveToTitleメソッドが書いてありますが、これはタイトル画面へとシーンを遷移させるメソッドです。これを53秒後に実行するのは、カウントダウンの3秒・ゲームの制限時間である45秒が終了してからさらに5秒後にシーンを遷移させるためです。 

そして29行目でまたコルーチンを呼んでいますが、DelayMethod(117~120行目)は第1引数で指定した秒数後に第2引数で指定したメソッドを実行するコルーチンです。書き方が違うだけで機能はInvokeメソッドと全く同じです。29~32行目の書き方はラムダ式と呼ばれていて短く書けます。 

では続いてUpdateメソッドに移ります。Updateメソッドは39~46行目は画面に表示させる得点の処理を行っています。そもそもGameManager.csにはscoreとdispayscoreという二つの得点を表す変数が用意されていますが、これは画面に表示させる得点が10点刻みで変化するのを実装するためです。得点が変化したらまずscoreを更新し、displayscoreがscoreと一致していなかったら10刻みで更新していきます。 

54行目のTime.deltaTimeは1フレームの長さを表していて、これをtimeから引き続けて制限時間を減らしていきます。 

72~90行目のメソッドはコメントにある通りです。 

   

PlayerController.cs

PlayerController.csのUpdateメソッドの中ではプレイヤーがステージ外に落ちたときにステージ中央に戻すという実装をしています。24,25行目ではプレーヤーの座標を指定しており、プレイヤーがこの座標にいたらif文が実行されます。まず26行目ではプレイヤーの移動速度を0にしています。これは速度がついた状態でステージ外に落ちると、その速度が保存された状態でステージ上に復帰し、場合によると無限にステージ外へ落下し続けるかもしれないからです。次に27行目では復帰先の座標を指定しています。そして28行目では、ステージ外に落ちたペナルティとしてscoreを引いています。最後29行目で、ステージ外に落ちたことを表す効果音を鳴らします。 

続いてOnCollisionEnterメソッドに移ります。このメソッドは、引数にとったオブジェクト(この場合はcol)に衝突した瞬間に呼び出されます。ただし引数の型がCollisionなので、衝突する方と衝突される方の両方にRigidBodyColliderコンポーネントをつけておかなければなりません。このメソッド内では、赤ボール・黄ボール・敵に衝突したそれぞれの場合を実装しています。衝突したオブジェクトの種類は「タグ」で見分けています(if文の条件指定でtagを使っています)。 

f:id:quietMikoshi:20190308182015p:plain
タグの設定
 

赤ボールに衝突したらPointBallController.csのGetRedPointBallメソッドを実行、黄ボールに衝突したらPointBallControllerのGetYellowPointBallメソッドを実行、敵に衝突したらEnemyController.csのTouchEnemyメソッドを実行します。

   

PointBallController.cs

9,10行目はそれぞれ赤ボール、黄ボールをとったときに取得する点数です。 

Updateメソッド内ではステージ外に落ちたボールをDestroyメソッドを使って削除しています。 

GetRedPointBallメソッドGetYellowPointBallメソッドではプレイヤーがボールに触れた瞬間に点数が加算されボールが消えるようになっています。 

   

Gimmick1.cs

ステージ1~5に共通することですが、5行目で赤いボール・黄色のボールのプレハブを格納します。また、ステージ1では触れるとプレイヤーが吹き飛ばされる敵を実装するので、6行目で敵のプレハブを格納しています。7行目もステージ1~5に共通していますが、得点をResult変数に格納しています。シーンが遷移してもResult変数の値が保持されるようにstaticをつけるのを忘れずに。 

9行目のred_or_yellow変数は、この値が0以上2以下だったら黄色ボールを作り、3だったら赤いボールを作るという基準を設けるために宣言しておきます。 

さてStartメソッドに入ります。16行目でGameManager.csにあるflagを取得しています。GameManager.csとGimmick1.csを同じオブジェクトにくっつけているので、このような記述になります。 

f:id:quietMikoshi:20190305175318p:plain
GameManager.csとGimmick1.csを同じオブジェクトにくっつける
 

20~23行目で敵の出現位置を初期化しています。図にすると、下図の赤い線分1本の上のどこかランダムに1つずつ敵が出現します。22行目のInstantiateメソッドは引数を3つとる場合、第1引数がオブジェクトそのもの、第2引数がオブジェクトを出現させる座標、第3引数がオブジェクトをどれだけ回転させた状態で出現させるかを指定します。 

f:id:quietMikoshi:20190305181316p:plain
敵の出現場所
 

Updateメソッドに行きます。31~38行目がボールの生成処理です。まずTime.deltaTimeを使ってdeltaを増やし続け、deltaがSPAN(=1.0f)を超えたらボールを1個生成します。「もし超えたら」の処理が34行目のif文です。if文の中では、まずdeltaを0に戻し、次にボールの色をランダムで決め、最後にCreatePointBallメソッドでボールを生成します。CreatePointBallメソッドでは、出現座標をランダムで決めてからInstantiateメソッドでボールを出現させています。

   

EnemyController.cs 

 

敵はflagがtrueのときだけ動くようにするので、Updateメソッドの中でif文を使って実装しています。if文の中で使っているtransform.positionはこのスクリプトをくっつけたオブジェクトの座標を取得します。+=や-=で座標を更新し続けて、敵が等速で動いているように実装します。26,27行目では敵の座標が一定値を超えたらLeftOrRightの値を変更して、敵の進行方向を逆向きにしています。 

TouchEnemyメソッドに移ります。34行目のdirectionは敵から見たプレイヤーのベクトルを表しています(Normalizeでベクトルの大きさを1にしています)。このdirectionの方向にプレイヤーを吹き飛ばします。35行目ではプレイヤーが山なりの軌道を描くようにy成分をいじっています。最後に36行目では実際にプレイヤーに力を加えています。 

   

Gimmick2.cs

ステージ2では床が上下に動くという仕掛けになっているので、7行目で床のプレハブを格納する変数を宣言しています。そしてStartメソッドの中にある21行目のfor文で床の初期位置を決めています。床は縦3×横3という形状なのでfor文で実装するとコンパクトになるだろうと思って書きました。 

それ以外の部分はほとんどGimmick1.csと同じです。ただしCreatePointBallメソッド内でボールの発生位置のy座標が13.0fになっています。これは、床が上下に移動するために、Gimmick1.csと同じくy座標を0に設定すると床の下側にボールが発生する場合があり、そのままボールが下に落ちていくだけになるのを防ぐためです。床は最大でもy座標が10までしか上がらないように設定してあるのでボールのy座標を13にしてあります。  

   

FloorController.cs

FloorController.csの実装は、数値や移動方向が変わっただけでEnemyController.csの実装と同じです。 

   

Gimmick3.cs

Gimmick3.csがGimmick1.csと違うのは、CreatePointBallメソッドの中でAddForceメソッドを使ってボールに対して発生時に力を加えているところです。AddForceメソッドは45行目と52行目にありますが、使う際にはGetComponentRigidBodyにアクセスする必要があります。 

   

Gimmick4.cs

7行目で床のプレハブを格納する変数を宣言しています。また12,13行目にPlaneSpanplanedeltaという変数が増えています。これはステージ4の床が消える仕掛けで使います。

さて床が消えたり生まれたりする仕掛けを作るのでUpdateメソッドを工夫しなければなりません。31~36行目は今までと同じです。40~46行目ではランダムな位置の床を縮小少しだけ縮小させています。Time.deltaTimeを使っているのはボールを発生させる実装と同じ原理です。まず43行目でposに小さくする床の位置を格納し、44行目でその床の色を緑に変えます。最後に45行目でその床を少しだけ小さくします。 

49~53行目では、大きさが0になっている床を元の大きさに戻し、色も水色に戻しています。 

58~60行目では、少しだけ小さくなった床を小さくし続けています。58行目の1.732という値が鍵なのですが、45行目で少しだけ小さくされた床はtransform.localScale.magnitudeの値がわずかに1.732を下回ります。この1.732という数字が大きすぎるとすべての床が小さくなってしまいますし、逆に小さすぎると一つも床が小さくなくなります。そして61~63行目では、ある程度小さくなった床の大きさを0にして見えなくします。大きさが0になった床は49~53行目の実装で復活するのでしたね。 

   

Gimmick5.cs

ステージ5では動く壁と回転するキューブを実装します。 

壁は一定間隔で発生するようにするので、今までと同じくTime.deltaTimeを使って37~41行目で実装しています。CreateWallメソッド内では発生させる座標をランダムに決めてからInstantiateメソッドで実際に発生させています。 

キューブの回転はtransform.Rotateを使えば44行目のように書けます。 

   

WallController.cs

WallController.csでは今までに解説してきたことしか使っていませんので、説明は大丈夫でしょう。 

   

ChangeScene.cs

9~13行目では各種アセットをpublicで格納しています。Unity側では下のようになっています。 

f:id:quietMikoshi:20190305143231p:plain
ChangeScene

Updateメソッドの29~33行目ではStage1~5の得点を一時的にResult[0]~[4]に格納しています。ここで、Gimmick1~5.csではResult変数はstaticにしておく必要があります。 

さて今ChangeScene.csのResult配列には現時点でのStage1~5の得点が入っていますが、このResult配列には今までの各ステージの最高得点が入っていなければなりません。そこで使うのがPlayerPrefsクラスのメソッドです。ここではその中のGetIntメソッドSetIntメソッドを使います。 

まず37行目では、Result[i]にResult[i]自身と"Maxi"というキーにおさめてある数(何もおさめられていなかったら0が返される)のうち大きな方を格納しています。これでResult[i]が常に今までの最高得点に更新され続けます。次に38行目では"Maxi"というキーに更新済みのResult[i]を格納しています。最後に39行目でResult[i]をテキストに出力します。 

48~86行目はStage1~5のボタンを押すと各ステージに遷移するときに使うメソッドです。ボタンを押すと効果音が鳴り、2秒後にシーンを遷移させるという実装になっています。  

f:id:quietMikoshi:20190305145506p:plain
ステージを遷移させるときに押すボタン
 

上図はStage1に遷移するのに使うボタンですが、この赤い枠内にChangeSceneManager(ChangeScene.csをつけた空オブジェクト)を入れ、青い枠内でChangeScene.SelectStage1を選択すればOKです。ただしSelectStage1メソッドはpublicにしておかなければなりません。この作業をStage1~5に施します。 

        

以上になります。今後もUnityで何か作ったら解説記事を書こうと思っているので、ご要望等あったらコメントに書いてもらえると嬉しいです!読んでくださってありがとうございました!