- 投稿日:2020-02-14T21:52:22+09:00
お手軽にAlexaスキルと Unity を連携させる (VoiceFlow)
Alexaスキルは、ノンコーディングで作れるサービスが多数あるので サクっと作成できます。
さらに Unity と連携させると、、、
「Alexa、ダンスを開始して」で、ユニティちゃんが踊りだす みたいなのが簡単に作れます。ということで、お手軽にAlexaスキルと Unityを連携する方法をまとめました。
Alexaスキル作成サービス
無料で始められる VoiceFlow を使います。他にもたくさんサービスがありますが、VoiceFlow は多機能で使いやすいUIが魅力です。
比較的新しのでたまにおかしな挙動もありますが、アップデートで徐々に改善されてきています。Unityで WebAPI を準備する
Alexa には WebAPI と連携する機能があるので、まず Unityで WebAPIを作ります。
HTTPサーバーを作成する
下記の Unity HTTPサーバーを作成し、再生しておきます。
前回記事:UnityでマルチスレッドなHTTPサーバーGetDataというリクエストがきたら、MyDataの値を返す。
SetDataというリクエストがきたら、MyDataの値を変更して、値を返す。
という簡単なAPIです。HTTPサーバーを外部公開する
Alexaスキルは、内部サーバーとは通信できない仕様なので、ngrok などで外部公開させておきます。
参考:【3分で出来る】ngrokでデプロイをしてみよう!ngrokは 起動するたびに URLがランダムに変わってしまうので、有料プランで固定ドメインにすると楽ちんです。
参考:ngrokのドメイン名を固定した時の「Bad Request」エラーを回避するVoiceFlow で Alexaスキルを作る
VoiceFlow は、Integration Block でカスタムAPI連携ができるので、これを使います。
適当なプロジェクトを作って、Unity からのレスポンスを取得できるか試します。Integration Block でレスポンスを取得する
Integration Blockを配置し、Start からラインを繋げます。
Integration Block を選択し、Custom API を選びます。
リクエスト内容は下記のように設定します。
Request URL には、上で設定した外部公開サーバーのURLを指定してください。
GetDataリクエストの場合、Params の Value は空でもいいはずなのですが、何故か テスト時にレスポンスが返ってこないので、適当に何か入れておきます。
Test Request を押すと Unity からのレスポンスを確認できます。
MyData クラス の success の値が返ってきました。
ちなみに success の横のクリップボードを押すと、変数の参照をコピーできます。
Alexaスキル内 の変数として格納したい時に使います。
Integration Block で値を送る
次にParams を変更して SetData リクエストを送ってみます。
ちゃんと Unity に届きました。会話を作りこむ
ここからは Unity 連携と関係なくなってくるので、割愛します。
VoiceFlow は簡単に会話を作れるので、好きに作りこんでみてください。いちおう、こんな感じのが作れます。
Alexa の会話で 変数の値を使うには
if blockで 変数の分岐をする場合は
Alexa スキル の テスト
Prototype タブに切り替えると PC上でテストできます。
Start Test を押すとチャットで会話がはじまります。
味気ないですが、一応会話らしきもので Unity と連携できました。Alexaデバイスとリンクしてビルドすれば、ちゃんと会話してくれます。
- 投稿日:2020-02-14T20:41:32+09:00
3次元姿勢推定の導入方法
三次元姿勢推定
Twitterにおいてこの方@yukihiko_aのツイートを拝見し、自分のPCでやってみた際の導入方法について説明します。
3次元姿勢推定の進捗。ResNet34ベースのモデルをUnity Barracudaで実装しています。
— Yukihiko Aoyagi (@yukihiko_a) February 13, 2020
こちらのコードをGithubにアップしました。
動画はこちら:https://t.co/RGQvmbnsgi pic.twitter.com/uj7pXBgMAD自身のPCの環境
CPU : Ryzen 7 1700
GPU : GeForce GTX1070
メモリ : 16GB
において実際において三次元姿勢推定を行いました。導入方法
英語での導入方法に関しては以下のgithubのREADME.mdにおいて詳しく説明していただいています。
なので、今回は日本語での説明及び、自分の環境においてつまずいた点を記載したいと思います。
3次元姿勢推定の続き。
— Yukihiko Aoyagi (@yukihiko_a) February 13, 2020
最新のコードを会社のリポジトリに公開しました。https://t.co/gvwPqAP1uh
パフォーマンスのレポートとして以下のようになっています。
GeForce RTX2060 SUPER ⇒ About 30 FPS
GeForce GTX1070 ⇒ About 20 FPS
(GithubにおけるプロジェクトのREADME.mdに記載されていました。)必要なプロジェクト及びファイルのダウンロード
githubから自身のPCにプロジェクトのダウンロードももしくはクローンを行います。Githubのリンク
次にonnxを以下のURLをクリックすることによってダウンロードを行います。
onnxUnity側での設定
Unity Editorを用いてUnityのプロジェクトを開きます。そして、Unityにおいて/Assets/Scripts/Model/ の位置に先ほどダウンロードを行ったonnx ファイルを置きます(画像の位置)。この作業によって自動的にNNModel Typeへの変換も自動的に行なわれます。
そして、Sceneフォルダの中にあるSampleSceneを開きます。その際にダイアログが表示されたら"Don't save"を選択してください。
モデルの設定を行います。先ほどAssets/Scripts/Model/の位置に置いたNNNModelをGameobjectの"BarracudaRunner"におけるInspector viewの中のNN Model に置きます。(Unity側での作業1における画像の右側)
4.デバックを行うことによって実際に三次元姿勢推定を行うことが出来ます。
動画の変更
Unityのプロジェクト内のAssets/Video/から動画を選択してHierarchyのVideo Player内のVideo Clipに置くことによって推定を行う動画の変更も行うことが出来ます。
ウェブカメラを用いる方法
MainTexrureのVideo Captureにおける"Use Web Cam"にチェックを入れることによってWebカメラを用いたリアルタイムでの推定を行うことが出来ます。
自分がつまづいた点について
今回自分の環境において導入する際に少しつまづいた点として挙げられるのが、Unityのバージョンについてです。
自分の使っていたバージョンでは、動作することが出来ませんした。
今回のプロジェクトに合わせて、Unity 2019.2.12f1を用いることによって導入することが出来るようになりました。まとめ
Webカメラや動画を用いた三次元姿勢推定をPC及びUnityで行うことが出来るようになりました。
自身でも動画を撮ってみて推定を行いましたが、とても制度が高かったです。
- 投稿日:2020-02-14T19:46:09+09:00
Unity で暗号化した SQLite (SQLCipher) を使うやり方のまとめ
暗号化はいらないときの基本
SQLite をシンプルに使うやりかたは、前の記事に書いたとおりです。
暗号化が必要になったとき
実際にアプリを公開するときに、DB ファイルの中身があっさり書き換えることができるのは、ちょっと……って思うなら暗号化がベスト。でも、これは自分で SQLite3 のライブラリーをコンパイルする道を選択したのと同じことだと思います。
GitHub - SQLiteUnityKit を利用しつつ Unity で SQLite を使うとき、暗号化するなら JAVA なんかがライブラリーの中に入ってくると邪魔になります。このキットはシンプルに DllImport で関数を呼び出してるだけです。
なので、なるべくシンプルに dll と so ファイルを作る必要があると思います。(x86/x64 win/android の4パターン)
このあたりを記事にまとめたので、ショートカットをメモ。
- Unity SQLiteUnityKit 暗号化 SQLite3 を Windows で利用する(DLL コンパイル)
- Unity SQLiteUnityKit 暗号化 SQLite3 を Android で利用する(.so コンパイル)
ビギナーなので、間違いがあったらすいません。(おしえてください)このあたりの記事は 2020/02 時点では、数が少ないので、もうすこしネタが増えると嬉しく思います。
- 投稿日:2020-02-14T18:09:18+09:00
Rustが流行ってほしい
Rustはゲーム開発に向いている理由
省メモリ
メモリや容量はゲーム開発をする上で一番大切な概念です。以前の記事を参照してください。ゲーム開発における言語はC,C++,C#,Python,Luaが殆ど全てといっていいほどです。Pythonは遅いですが、オブジェクト指向で書けるスクリプト言語且つ演算子オーバーロードが利用でき且つ省資源であることを考えると良い選択肢であるということを示しています。それ以上に遅い言語はPHP,ShellScript,PowerShell等の特定の物に特化した有名言語,scratch等の子ども用の言語くらいだと言われています。
高速
Rustの速度はCと同じかそれよりやや遅い、C++(の多くのコンパイラ)より速いのでとても高速に動作します。MLのようなマクロや束縛等で最適化しやすいためという理由もあります(高速なライブラリの、readonlyを利用したインラインconst化)。C++のような"std","演算子オーバーロード",C#のような"const","for","use","ジェネリクス","型推論"等のゲームエンジニアがよく利用するであろう機能が存在します。stringについては組み込み型(str)とstd::string::Stringが存在します。C#もGCを省いた速度(GCが無ければ起動3秒後以降、C++の1.1倍くらいしか速度が変わらない)では問題がないですが、いつ起こるかわからないのでそこら辺の管理が大変です。またC#やJava並みに可読性が高い且つ、C++やC#の慣れている人だと学習コストが低いのでメリットが多いです。
バグが起こりにくい
これは意外に重要です。よくゲームで実行時バグだったりクソゲーだったりも多いですが、その原因の多くはバグを生みやすい自由度にあります。多くは、マクロやtemplateや多重継承やgotoやdelateし忘れ等がいい例です。また、ゲームエンジンを使わない多くの場合組み込みエンジニアのようにアセンブラ他でハードウェア毎の実装をしなくてはなりません。
DirectX >>> ハードウェア->抽象化->プログラム->具体化->ゲーム->抽象化->プログラム->具体化->ハードウェア
これは多くの場合ゲームを作ることが目的になり、(ほんの少数の天才以外は)感性で面白いと感じるゲームを作ることが後回しになることが多かったのでゲームエンジンが生まれました。一つの文やオブジェクトで具体→抽象→具体と三段階踏まないとならないのはとても頭を使います。
UE4 >>> プログラム->具体化->ゲーム->抽象化->プログラム
こうなると理性に使っていたリソースを感性に使うことができるので、作っている途中にクソゲーだと気が付きわかりやすいので、客からの信用を落とさずに済みます。また、バグの多くもエンジン側によって最適化処理されているためマシです。但し、これにも問題があります。マクロの使用や無駄なtemplateの使用や多重継承やgotoの使用やdelateし忘れが発生している可能性が秘めているという点です。これを解決するであろうRustは非常に純粋で美しくC++erに優しい仕様となっています。これら問題は全てRustが解決し、ifは式、安全で高速、変数は束縛(下で詳しく話します。)というゲーム利用に最適化された機能がある点にも注目できます。
@comment Unityがゲームエンジンではないと声高に叫んでいるバカがいたのですがUnityはゲームエンジンです。無論UnityでもC#でのGC特有の問題も存在します。デフォルトがReadOnly
グーグルのC++ガイドラインで
理にかなっているのならば、常にconstを使ってください。 C++11では、いくつかのconstは、constexprを使うほうがよりよい選択です。
土方プログラマーでなければ、プログラムを書いているとconst autoだらけになることも多いのではないでしょうか?const_castを使うことも多いので、束縛は重要です。また、ReadOnlyの方が大胆な最適化が可能です。従って今後はゲームにRustを使うことになるのではないかと思っています。また、Rustの束縛はreadonlyを利用したインラインconst化で高速です。
- 投稿日:2020-02-14T15:08:57+09:00
【Unity】standardAssetsの車のタグ付けについて(ど忘れすると沼にハマる系)
- 投稿日:2020-02-14T12:32:41+09:00
Unityで始めるゲーム制作1
はじめに
もっぱら技術ブログなどは、
自分が所属している同人サークル「RomanesqueFreaks」のブログで書いてたんですけど、
Unityの導入部分くらいはこっちにも書いちゃおうと思ったので、書きます。技術系やゲーム・IT系のイベントの話をしてるので、
是非ブログものぞいていってください!環境
Windows10
Mac(スクリーンショットはこちらの画面です)インストール
現在のオススメは複数バージョンのUnityを管理できるUnity Hubです。
こちらから「Unity Hubをダウンロード」を選択してダウンロードしてください。
exe/dmgを実行するとHubがインストールされます。
テキストエディタのインストール
Unityでの開発は主に、Unityのエディタを開きながらオブジェクトを配置したりして、それに対してC#を別のテキストエディタで書いていく、という流れになります。
(個人的にデュアルディスプレイがまじで使える場面です!)フリーで使えるエディタの中ではVisual Studioがとても強いのでインストールしてみましょう。
今回は個別にインストールしますが、もともと入っている場合はそれを使うことができるので、この手順はスキップしてください。
Visual Studioは統合開発環境、英語にした時の頭文字でIDE (Integrated Development Environment)と呼ばれる高機能なエディタです。
そのためPCのスペックが高くない時には、処理が重く大変になるかもしれません。
そんな時はVS Codeと呼ばれる Visual Studioの低機能軽量版での開発をお勧めします。
自分も一時期この環境で開発してました。
詳しくはこちらを。ではエディタのインストールの手順に入ります。
まず、Unity Hubを実行し、「インストール」をクリック。
インストール済みUnityのメニュー(グレーの3つの点)を選択。
「モジュールを加える」を選択
Windowsでは「 Microsoft Visual Studio Community 2017」、
Macでは 「Visual Studio for Mac」を選択し、「次へ」を押す。
すると規約が表示されるので、了承できる場合は「実行」を押すとインストールが開始されます。
- 投稿日:2020-02-14T12:32:41+09:00
Unityで始めるゲーム制作 導入編
はじめに
もっぱら技術ブログなどは、
自分が所属している同人サークル「RomanesqueFreaks」のブログで書いてたんですけど、
Unityの導入部分くらいはこっちにも書いちゃおうと思ったので、書きます。技術系やゲーム・IT系のイベントの話をしてるので、
是非ブログものぞいていってください!環境
Windows10
Mac(スクリーンショットはこちらの画面です)インストール
現在のオススメは複数バージョンのUnityを管理できるUnity Hubです。
こちらから「Unity Hubをダウンロード」を選択してダウンロードしてください。
exe/dmgを実行するとHubがインストールされます。
テキストエディタのインストール
Unityでの開発は主に、Unityのエディタを開きながらオブジェクトを配置したりして、それに対してC#を別のテキストエディタで書いていく、という流れになります。
(個人的にデュアルディスプレイがまじで使える場面です!)フリーで使えるエディタの中ではVisual Studioがとても強いのでインストールしてみましょう。
今回は個別にインストールしますが、もともと入っている場合はそれを使うことができるので、この手順はスキップしてください。
Visual Studioは統合開発環境、英語にした時の頭文字でIDE (Integrated Development Environment)と呼ばれる高機能なエディタです。
そのためPCのスペックが高くない時には、処理が重く大変になるかもしれません。
そんな時はVS Codeと呼ばれる Visual Studioの低機能軽量版での開発をお勧めします。
自分も一時期この環境で開発してました。
詳しくはこちらを。ではエディタのインストールの手順に入ります。
まず、Unity Hubを実行し、「インストール」をクリック。
インストール済みUnityのメニュー(グレーの3つの点)を選択。
「モジュールを加える」を選択
Windowsでは「 Microsoft Visual Studio Community 2017」、
Macでは 「Visual Studio for Mac」を選択し、「次へ」を押す。
すると規約が表示されるので、了承できる場合は「実行」を押すとインストールが開始されます。
続く
(2月下旬執筆予定)
- 投稿日:2020-02-14T12:21:13+09:00
【Unity】Sceneを切り替えるコード
これでスタート画面やエンド画面を作ることができる!!
例では、SPACEキー押下で、SceneStartというSceneファイルへ遷移するようにしている。
//この一文は必要 using UnityEngine.SceneManagement;if(Input.GetKey(KeyCode.Space)){ SceneManager.LoadScene("SceneStart"); }Targetというタグに触れたらゲームオーバー的な演出をしたい場合は下図参照
if (col.gameObject.tag == "Target") { SceneManager.LoadScene("SceneEnd"); }
実行時は、ビルド設定で、Sceneファイルを含めておく必要があるので、スクリプトを書いて満足しないように!!
- 投稿日:2020-02-14T06:00:17+09:00
Unityでシューティングゲームを作る(5)
ここまでの進捗
- 背景がループするようにした。
- 普通の敵の動作を作成し、その敵が3秒ごとに生成される。
- 瞬間移動する敵の動作を作成し、5秒ごとに生成する。
- プレイヤーが画面の範囲外に行かないようにした。
- 敵とプレイヤーが衝突したらプレイヤーが消滅する。
- 分散攻撃の敵を実装する。
- タイトルシーンとエンディングシーンを追加する。
- プレイヤーがダメージ受けると点滅して数秒だけ無敵状態になる
今後やること
- ボスキャラの動作を実装する。
- エフェクトとBGMを追加する。
- プレイヤーが横に移動すると機体が傾くアニメーションをつける
この記事では赤い部分を作成した。
傾くアニメーション
これを実装する際にしたミスを含めて書きたいと思う
まずanimationを作成するには上のように
[window]→[Animation]→[Animation]を選択する
そうすると以下のようにAnimator controllerとAnimatorコンポーネントとAnimation Clipが作成される
最初に試した方法
Animation Clipの中で設置するひし形のものをキーという。
Animation Clipを編集するが、傾きをrotateで表せばいいと思っていた。
0.10,0.20,0.30の位置にY軸にそれぞれ30,40,50で回転させたキーを置いた。これの問題点
実行してみるとボタンを押したときに回転するが、なぜか少ししたらプレイヤーの機体が消えてしまう。
原因を調べてみたらどうやらZ座標がマイナス方向に増えていってしまい、カメラよりも後ろにプレイヤーの機体が行ってしまっていることが分かった。
おそらく30や40に傾けた上でtranslateで移動しているのでz軸方向にも移動してしまったと思われる。次に試した方法
gameの中でプレイヤーの機体をY軸で傾けたものをスクリーンショットで撮り、それをUnity内でSprite Editorを用いることで余計な部分から切り抜いた。
Sprite EditorのCustom Outlineで以下のように点をとって切り抜いていくこれを右に傾けた時と左に傾けた時で作成してAnimation Clipに以下のようにそれぞれ配置する。
このクリップをAnimator Controllerで遷移させる。作成したクリップをAnimator Controller上にドラック&ドロップする。
このとき遷移させる条件を指定しないといけないので左上のParametersから[+のマーク]→[Bool]を選択する。これでスクリプトの中でParametersのパラメータをtrue or falseにすることで遷移させることができる。
Has Exit Timeのチェックを外してTransition Durationを0にする
Conditionsの+マークをおして遷移条件を作成する。後はスクリプトでタップしたらAnimationが動作するようにする
//タッチ判定 if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if (touch.position.x < Screen.width * 0.5f) { //画面外に行かないようにする if (-3.1 < transform.position.x) { transform.Translate(-0.05f, 0, 0); if (touch.phase == TouchPhase.Began) { //押した時 anim.SetBool("left_long", true); } if (touch.phase == TouchPhase.Moved) { //長押しの時 anim.SetBool("left_long", true); } if (touch.phase == TouchPhase.Ended) { //指を離した時 anim.SetBool("left_long",false); } } else { transform.Translate(0, 0, 0); anim.SetBool("left_long", true); } } else if (touch.position.x > Screen.width * 0.5f) { //画面外に行かないようにする if (3.1 > transform.position.x) { transform.Translate(0.05f, 0, 0); if (touch.phase == TouchPhase.Began) { //押した時 anim.SetBool("right_long", true); } if (touch.phase == TouchPhase.Moved) { //長押しの時 anim.SetBool("right_long", true); } if (touch.phase == TouchPhase.Ended) { //指を離した時 anim.SetBool("right_long",false); } } else { transform.Translate(0, 0, 0); anim.SetBool("right_long", true); } } }例えばanim.SetBool("left_long", true)でParameter"left_long"をtrueにするので左に傾くアニメーションを流す。
スクリプトの内容を説明するとInput.touchCount > 0 でタッチされているかチェックする。
Touch touch = Input.GetTouch(0)は長押しなどのタッチされた時の状態を取得している。
条件の中にあるtouch.phase==TouchPhase.Beganは「タッチしたとき」、touch.phase == TouchPhase.Movedは「長押ししてるとき」、touch.phase == TouchPhase.Endedは「指を話したとき」の判定をしている。これでできたのが以下になる。
これ簡単にみえるけどつまづいたところを調べたりしてかなり時間かかってしまった。
これであとはボスを作るだけになった。
- 投稿日:2020-02-14T06:00:17+09:00
Unityでシューティングゲームonomatihar
ここまでの進捗
- 背景がループするようにした。
- 普通の敵の動作を作成し、その敵が3秒ごとに生成される。
- 瞬間移動する敵の動作を作成し、5秒ごとに生成する。
- プレイヤーが画面の範囲外に行かないようにした。
- 敵とプレイヤーが衝突したらプレイヤーが消滅する。
- 分散攻撃の敵を実装する。
- タイトルシーンとエンディングシーンを追加する。
- プレイヤーがダメージ受けると点滅して数秒だけ無敵状態になる
今後やること
- ボスキャラの動作を実装する。
- エフェクトとBGMを追加する。
- プレイヤーが横に移動すると機体が傾くアニメーションをつける
この記事では赤い部分を作成した。
傾くアニメーション
これを実装する際にしたミスを含めて書きたいと思う
まずanimationを作成するには上のように
[window]→[Animation]→[Animation]を選択する
そうすると以下のようにAnimator controllerとAnimatorコンポーネントとAnimation Clipが作成される
最初に試した方法
Animation Clipの中で設置するひし形のものをキーという。
Animation Clipを編集するが、傾きをrotateで表せばいいと思っていた。
0.10,0.20,0.30の位置にY軸にそれぞれ30,40,50で回転させたキーを置いた。これの問題点
実行してみるとボタンを押したときに回転するが、なぜか少ししたらプレイヤーの機体が消えてしまう。
原因を調べてみたらどうやらZ座標がマイナス方向に増えていってしまい、カメラよりも後ろにプレイヤーの機体が行ってしまっていることが分かった。
おそらく30や40に傾けた上でtranslateで移動しているのでz軸方向にも移動してしまったと思われる。次に試した方法
gameの中でプレイヤーの機体をY軸で傾けたものをスクリーンショットで撮り、それをUnity内でSprite Editorを用いることで余計な部分から切り抜いた。
Sprite EditorのCustom Outlineで以下のように点をとって切り抜いていくこれを右に傾けた時と左に傾けた時で作成してAnimation Clipに以下のようにそれぞれ配置する。
このクリップをAnimator Controllerで遷移させる。作成したクリップをAnimator Controller上にドラック&ドロップする。
このとき遷移させる条件を指定しないといけないので左上のParametersから[+のマーク]→[Bool]を選択する。これでスクリプトの中でParametersのパラメータをtrue or falseにすることで遷移させることができる。
Has Exit Timeのチェックを外してTransition Durationを0にする
Conditionsの+マークをおして遷移条件を作成する。後はスクリプトでタップしたらAnimationが動作するようにする
//タッチ判定 if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if (touch.position.x < Screen.width * 0.5f) { //画面外に行かないようにする if (-3.1 < transform.position.x) { transform.Translate(-0.05f, 0, 0); if (touch.phase == TouchPhase.Began) { //押した時 anim.SetBool("left_long", true); } if (touch.phase == TouchPhase.Moved) { //長押しの時 anim.SetBool("left_long", true); } if (touch.phase == TouchPhase.Ended) { //指を離した時 anim.SetBool("left_long",false); } } else { transform.Translate(0, 0, 0); anim.SetBool("left_long", true); } } else if (touch.position.x > Screen.width * 0.5f) { //画面外に行かないようにする if (3.1 > transform.position.x) { transform.Translate(0.05f, 0, 0); if (touch.phase == TouchPhase.Began) { //押した時 anim.SetBool("right_long", true); } if (touch.phase == TouchPhase.Moved) { //長押しの時 anim.SetBool("right_long", true); } if (touch.phase == TouchPhase.Ended) { //指を離した時 anim.SetBool("right_long",false); } } else { transform.Translate(0, 0, 0); anim.SetBool("right_long", true); } } }例えばanim.SetBool("left_long", true)でParameter"left_long"をtrueにするので左に傾くアニメーションを流す。
スクリプトの内容を説明するとInput.touchCount > 0 でタッチされているかチェックする。
Touch touch = Input.GetTouch(0)は長押しなどのタッチされた時の状態を取得している。
条件の中にあるtouch.phase==TouchPhase.Beganは「タッチしたとき」、touch.phase == TouchPhase.Movedは「長押ししてるとき」、touch.phase == TouchPhase.Endedは「指を話したとき」の判定をしている。これでできたのが以下になる。
これ簡単にみえるけどつまづいたところを調べたりしてかなり時間かかってしまった。
これであとはボスを作るだけになった。