2020年自作ゲーム総括

#本題について
趣味でグラディウス風（特にゲーセン版の3作目を意識して）自作ゲームを作成して約3年半経過しまして、
今年もかなりの改修をしました。

今年の総括として、ここに記載します。

## 自作ゲームとは
（詳細は、別記事で紹介する予定です。）
![00021230_105047.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/d4fdcd49-ba37-d185-9854-2e53f6b1490d.gif)

グラディウス風の横スクロールシューティングゲームです。
一部制約はありますが、基本的にPC・スマホ（※）でゲームを楽しめます。
言語はJavaScript・scss・htmlのみで、Canvasで描画しています。
※PCはMacOSの最新版、スマホはiOS、iPadOSの最新版のみ対応
![Screen Shot 2020-12-27 at 15.38.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/d45c8cdc-8ac1-d964-2f8b-af9a352916fc.png)

ちなみにJavaScriptのファイル数は350近くありました。
![HTML 5 Shooting Game 2020-12-19 22-01-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/07e67670-47d1-cdf3-a18a-fe0c1a12a2a6.png)
流石にこのリクエスト数に難があると思うので、
JavaScript、CSSを圧縮し、それらをHTMLファイルと一緒に纏めたビルドコマンドも用意してます。

## 2020年に自作ゲームで改修したこと

### 画像、効果音、サウンド制作

今年前半は、ソース改修は殆ど行わず、
画像（イラスト制作）、効果音、サウンド制作がメインでした。
詳細を下記します。

##2020年に自作ゲームで改修したこと(1) 画像作成

制作期間は、約6ヶ月ぐらいでした。

ドット絵で描く方針でいまして、幾つかアプリを試した中で、
**MediBang Paint**を選定。iPad Pro(2018)を使って描きました。
（本当はPhotoshopのiPad版で描きたかったけど、ドット絵が描けなかった。。）

---
余談ですが、iPad Proシリーズは初めてで、かつ、初めてのApple Pencilでした。
幾つかサードパーティのスタイラスペンを試しましたが、
**Apple Pencilの描き心地は抜群**でした。

---

実装ずみのCanvasサイズが1000x500pxだったこともあり、
かなりの高解像度で描く必要があったため、
大きいキャラクターのドット絵を描くのにかなり苦労しました。

![IMG_6AD60DB874A4-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/65b93e7d-c6af-5ab8-e1e0-6872c06c94e7.jpeg)
MediBang Paintでは、描いた絵の一覧を表示するマイギャラリーがある。
※ちなみに、右側の幾つかの画像は「石」をモチーフにしてます。。

![00021227_205545.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/6bcdc3c9-b0dc-3559-7083-18e7ea847134.gif)
自分の中で出来が一番よかったのは、この敵キャラクターです。
キャラクターをたくさん描き、機体の構成等理解できるようになってから、
この敵キャラクターを描いたので、自分が納得できるデザインに仕上がったかなと思っています。

##2020年に自作ゲームで改修したこと(2) 効果音・サウンド作成
サウンド作成：GarageBand（MacBook12 → MacBook Pro 2020）

最初は、iPadか、PCのキーボードで打ち込みしようと思ったのですが、
特に2オクターブ以上の表現をしたい時に、iPadやPCではあまりにも不便すぎたために、
お茶の水へ行って、MIDIキーボードを購入しました。
また、ゲーセン感を演出したいと、Dexedというプラグインを使いました。
制作期間は約1ヶ月半ぐらいでした。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">買ってしまった。<br>やるしかない。。。<br><br>YouTubeでいろんな情報を観まくってる。<br><br>録音したものを、jsのAudioContext使って、再生しようとしてるとこ。 <a href="https://t.co/2AxlraM3t7">pic.twitter.com/2AxlraM3t7</a></p>&mdash; Takahashi Masaya (@ma_taka) <a href="https://twitter.com/ma_taka/status/1289165759311015936?ref_src=twsrc%5Etfw">July 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

すでにコーディングで8ステージ分実装してたので、
少なくとも8曲以上は作らないといけない・・・。
1曲を最低でも8小節以上と決めてました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ドキュメンタリーな曲になった。笑。<br>残り1ステージ。<br><br>この装備は、他の装備に比べて一番難しいし、<br>湿度高いせいか、指紋ベタベタになり、<br>タッチパネルでのスムーズな操作できないな。。<a href="https://t.co/ycGf2NTkBl">https://t.co/ycGf2NTkBl</a></p>&mdash; Takahashi Masaya (@ma_taka) <a href="https://twitter.com/ma_taka/status/1294254529836277760?ref_src=twsrc%5Etfw">August 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

全ての効果音、サウンドが出来上がった中で、この曲は思い入れがありました。
ずっと寝かし続けてた、口ずさみ程度の自作曲を持ち出し、
それを、シューティングの雰囲気をイメージして編曲しました。
こういう形で使われるのに、不思議な感じでした。


##2020年に自作ゲームで改修したこと(3) 実装済ソースの構成変更

これまで実験的な改修を積み重ねたソースコードだったので、
ここは精査しました。

DDD、クリーンアーキテクチャーなど、参考文献を色々と漁りましたが、
最終的に自分の結論として、

**責務が明確になっていること**

を、しっかりできていればそれで良いかなと思い、
以下のUML図を作成しました。
そして、それを元にソースコードを見直しました。
全体を見渡せたことで、不要な処理・変更による影響範囲等が明確になり、
改修等が随分と楽になりました。

### UML図
![overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/baa33a11-7524-7235-4a54-7a7b8f48132c.png)
自分なりのUML図（間違い等ありましたらすみません。。）
※Visual Studio CodeのPlant UMLプラグインで作成しました。

- Presentation 入出力デバイスを管理
- Application このゲームのメイン処理（オープニング、ゲーム中等をシーンで管理）
- Repository firebase、CMS系に、ステージ情報を保存
- Domain シーン上で動かすキャラクター等を管理


##2020年に自作ゲームで改修したこと(4) もうちょっと細かい話

以下は既に実装済みですが、もう少し精査したいと思いまして。
幾つか改修した中で、一部ピックアップしたいと思います。

###レーザーの改修 - 衝突判定を精査したい

当初、レーザーは「一本のデータ」でした。
データの構成は以下で、一本のレーザー間に敵・障害物があった場合、
レーザーの先端を手前にする処理を入れてましたが、どうもレーザーの流れが不自然に思え、
しばらくはその善処が見出せない状況でした。
![Screen Shot 2020-12-29 at 16.56.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/f6bf8bea-065b-ac99-fc8e-746fb3cd2709.png)
- x1:左端のx位置(Number)
- x2:右端のx位置(Number)
- y:y位置(Number)

妙案が思いつかなかった時に、[グラディウスIII](https://ja.wikipedia.org/wiki/グラディウスIII_-伝説から神話へ-)のWikiを拝見したら、
レーザーの説明にヒントがありました。

```
NORMAL LASER（ノーマルレーザー）
前方にザコを貫通する直線状のレーザーを発射。ボタンを押している間しばらく伸び続け、射線が自機のY軸移動に連動する。他作品のレーザーより短めで、耐久力の高い標的に当たっている間は切れ間無く照射される反面、貫通性が低く、感覚的には通常弾の連射のような扱いになっている。このような性質から、イオンリングを連射中のモアイをリングもろとも破壊したり、耐久力の高い標的の多い場面でワインダーによって広範囲にダメージを与えたりという、前作で使用できた戦法は取れなくなっている。

Wikiより一部抜粋（2020/12/28時点）
```

この「通常弾の連射のような扱い」がヒントになりました。

それで、レーザーの構成を改めて以下に変更しました。

![Screen Shot 2020-12-29 at 16.59.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/0c094f31-9032-d3e4-cbf2-8b1c47b3b451.png)
1本のレーザーに対して、一定区間に以下の情報をもつ配列を用意しました。

- x:x位置（左端）(Number)
- y:y位置(Number)
- collided:衝突フラグ（Boolean 衝突した:true、衝突しない:false）

そして、ある区間で衝突が発生した場合、その区間の衝突フラグをtrueにします。
以降、衝突判定処理しない、かつレーザーを表示しないようにします。
![Screen Shot 2020-12-29 at 16.59.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/40c42531-6b23-0786-7df5-9fe6d12aa676.png)

改修後の状態が以下画像です。
火山の障害物に対するレーザーの動き、途切れ具合が不自然なく表現できたかなと思います。
**
ただ、レーザー装備の攻撃手段「ワインダー」ができない感じで。
障害物の後ろの敵を倒せないという・・・。
**
![00021227_210357.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/1ef25b7b-59e0-e49a-8fde-bcfb75622206.gif)


###PC版、同時押改修

PCではキーボードで操作します。操作内容は以下です。

| キー | PLAYING |
:--:|:--: 
| ↑ | 上へ移動 |
| → | 右へ移動 |
| ↓ | 下へ移動 |
| ← | 左へ移動 |
| SPACE | ショット（ミサイル含） |
| B | 装備 |
| P | 一時停止 |
| S | ステージ選択に戻る |
| R | ステージの最初に戻る |

識者の方から教授頂きまして（大変助かりました）、
斜め移動できるよう、同時押し（右上であれば、→と↑同時押し）できるように改修しました。

そのおかげで、以下図のように、コントローラーでゲームもスムーズにプレーできるようになりました。
![IMG_2585.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130301/da799442-b0eb-330e-bd5f-b645ad9ded22.png)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こちら詳細を投稿しました。<a href="https://t.co/I7bS9kQZ9c">https://t.co/I7bS9kQZ9c</a></p>&mdash; Takahashi Masaya (@ma_taka) <a href="https://twitter.com/ma_taka/status/1298996973249339393?ref_src=twsrc%5Etfw">August 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 今後の課題

### Service Workerのキャッシュ問題
この自作プログラムに、Service Workerを導入してます。
オフラインでもゲームできます。

ただ、ソースを更新しても、キャッシュクリアがうまくいかず、ブラウザで更新されないです。。
（シークレットモードでは大丈夫っぽいです）
端末でキャッシュクリアせざるを得ない状況を、次の改善にしたいです。

## まとめ
もともとは、JavaScriptのスキルアップがきっかけで、このゲームを作成しました。
2017年から実装を始めてから、約3年半経過しました。
JavaScriptとCanvasだけで、ここまで作れてしまうんですね。

この時期は、端末のスペックもそこそこ充実してたと思いますし、
また、コーディングする上で、配列・変数を無駄遣いしない意識で実装したおかげで、
多少古い端末でも動かせてると思います。

今後は、新しい技術等に関わる機会を増やしていきたいと思い、
課題以外については、一旦この自作ゲームの着手は終了し、
別の新しい自作ゲームの開発を進めています。

それが完成したら、Qiitaで紹介する予定です。

## 参考
- [グラディウスIII -伝説から神話へ-](https://ja.wikipedia.org/wiki/グラディウスIII_-伝説から神話へ-)
- [800種類以上のブラシ・トーンが無料で使えるペイントアプリ –メディバンペイント-](https://medibangpaint.com)
- [DEXED](http://asb2m10.github.io/dexed/)
- [Plant UML](https://marketplace.visuals)