はじめに
この度、内定直結型エンジニア実習アプレンティスの課題として、第二回チーム開発を行いました。その説明・雑感などをまとめます。文字の多い記事ですが、読んでやってください。
1. 自己紹介
弁護士を目指して法学部に進学、大学を休学して独学で司法試験の合格を目指すも挫折。人生に悩んでいたところ、以前からプログラミングに興味があったことを思い出し、2024年1月29日から学習開始。4月からアプレンティス5期生。出身は北海道。
趣味は映画鑑賞で、何もない1日は映画を6本くらい見ることも。好きな映画はコメディなら「トゥルーマンショー」と「ハングオーバー」、サスペンスなら「ナイトクローラー」と「メメント」、ヒューマンドラマなら「グリーンブック」と「きっと、うまくいく」、SFなら「マイノリティリポート」と「レディプレイヤー1」、ホラー(?)なら「シックスセンス」、アクションなら「イコライザー」。「レディプレイヤー1」は万人ウケすると思うので、この記事を読んだ人は必ず見てください。
2. 仕様技術
・HTML/CSS
・JavaScript
・PHP/Laravel
・MySQL
・Git/GitHub
・ChatGPT
・その他生成AI
3. アプリ説明 - evolA
3-1. 概要
今回開発したのは恋愛シミュレーションゲーム、evolAです。ただの恋愛シミュレーションゲームではなく、ヒロインがときたま逆再生の音声で話しかけてくるので、それを何と言っているか聞き取って選択肢に挑み、好感度を上げていくというゲームです。
そもそも逆再生の音声を聞き取ることは可能なのか?というところはあると思いますが、コツはあります。例えば「ありがとう」なら「うとがりあ」となるように思えますが、実はそうではなくarigatouをひっくり返したuotagiraから「うおたぎら」となります。「赤坂」はakasakaなので逆再生しても変わりません。
アプリ名はこれらを踏まえて決定しました。具体的には以下の通りです。
A love → Alove → evolA
不可算名詞のloveにaがつくのは文法的に正しくありませんが、複数のヒロインのうちから一人を選ばなければならないという点からloveを可算なものと捉えているという意味で、あえてaをつけています。(本当は最後は母音で終わらせたほうが発音しやすいから無理やりAをつけたのですが、これは秘密です。)
3-2. 実際の画面
スタート画面
本編画面
チュートリアル
3-3. 機能
3人のヒロインからひとりを選んで好感度を高めることを目的とするのが本編で、逆再生の音声を聞き取るための訓練をするのがチュートリアルです。BGMは場面ごとに設定され、右上の設定からBGMの音量調整とテキスト表示スピードの調整が可能です。
ゲーム開始から終了までリダイレクトは発生せず、シームレスなユーザー体験を提供しています。ここは設計段階からこだわったポイントです。
4. チームでの活動
4-1. アイデア出し
正直なところ一番苦労したのはアイデア出しでした。テーマは「ワクワクするものを開発せよ」なので、「ワクワクする」のはどういうものかを全員で羅列して共通点を探るという方法を実施しましたがそれでは足りず、視点を変えて「イライラする」で同じ作業をしました。出揃ったパーツを組み合わせてそれっぽいアプリを考えてみると、おおよそ「地図を使った新発見アプリ」と「暇つぶし系ゲームアプリ」に大別されることに気づき、前者は無難すぎるということで後者に決定。
では具体的にどんなゲームを作るのかということを考えるも、既存のゲームをパクってもワクワクしないということで難航。そこで、「チームメンバーの共通点から考える」や「知っているフィクション作品から抽出する」という思考法を試した結果、映画「TENET」から「逆再生」を抽出することに成功します。最初は単純に「逆再生の音声が何を言っているか当てるクイズアプリ」を考えましたが、それでは面白味に欠けるということで、「逆再生の言語を話す女の子との恋を成就させる恋愛シミュレーションゲーム」というカオスなアイデアに至りました。
ちなみにやや後付け感はありますが、こういった類のアプリであれば第一回チーム開発で行った典型的なCRUD機能と重複することもなく、オブジェクト指向についても理解が深められるということもアイデア決定に一役買った節があります。
4-2. 要件定義・設計
ここでは完成物への認識をそろえる作業がまず大変でした。そもそも恋愛シミュレーションゲームに詳しい人がいるわけではなかったので、ノベル形式のゲームがどういうものかを調査するためにフリーゲームをいくつか遊んでみたりしました。
また、チームにゲームを作ったことがある人はいないため設計するのがかなり大変で、開発期間前は具体的に設計を詰めていくというよりも、どのような機能が必要かを列挙するのが主な作業でした。
4-3. 自分の担当作業
拡張性を意識したクラス設計
今回の開発で自分が一番こだわったところです。将来的に新ヒロインや新モードを追加するとなったときに備えました。コードの整理や役割分担に役立たせたいという目的もあります。
テキストを非同期でデータベースから持ってくる作業
これはJSONファイルにシナリオを書いておいてそこから持ってくる方法も考えたのですが、それではユーザーが検証ツールを開けば見えてしまい後の展開のネタバレを避けられないため、クリックごとにデータベースから持ってくる仕様にしました。ただ、この仕様で実際にデプロイしたらサーバーへの負荷が相当大きいのではという懸念はあります。
選択肢によるストーリー分岐
実装前は方針が全く思いつかなかったので少し苦労しました。シナリオはクリックごとにidがひとつずつ増えていく仕様なので、選択肢ごとに「シナリオidをスキップする数」を持たせることで実装しました。
シナリオ作成、登場人物の設定を作成
ChatGPTで作成しました。思いのほか言うことを聞いてくれず、自分で作成した部分も多いです。ここで凝り性が発動してしまい、わざわざ高校生の年間行事予定を調べて違和感ないように調整したり、「こういう言い回しだとヒロイン可愛くないよなあ」とか考えたり、全ての選択肢で「はい」が正解だとつまらないので意図的に「いいえ」が正解の選択肢も作ったりしたので、かなりの時間をここで費やしてしまいました。しかもプレゼン用に実装したのは作ったうちの2割ほどなのでちょっと悲しくなりました。
逆再生の音声を再生する
できあがった逆再生の音声をタイミングごとに再生する作業で、そこまで難しくはありませんでした。
アプリ名考案
3-1を参照。
一連の処理をすべての場面に使い回せるようにする
チュートリアルモードと各ヒロインのルートは機能上別次元のものであったのですが、仕組み上は同じものであることに気づけた点は我ながらファインプレーだと思います。
暗転演出のタイミングを調整
場面が切り替わる時の暗転で、背景画像が切り替わるときに一瞬白くなってしまうのを隠すための処理です。正直優先度は低いかなと思っていましたが、これを実装すると一気にそれっぽくなったのでやってよかったと思います。自分はCSSが苦手なため暗転処理自体はCSS担当の方にお願いし、できあがったものにkeyframesやsetTimeoutを設定しました。何度も試していい感じの秒数を探すという泥臭い作業をしました。
5. 個人での活動
5-1. 保身のための注意書き
チーム開発なので全員が努力した結果であるというのは大前提であるものの、せっかくこういう記事を書くのだから特に自分が頑張ったことをアピールさせていただきたいという趣旨です。主観として頑張ったことであり、結果としてチームに貢献したかどうかは微妙なものも含みます。
5-2. 具体的な活動
ミニプロダクト
開発期間の前半で、目的物のスケールを最小限にしてエッセンスだけ実装したミニプロダクトを作り、「こういう方針ならやりやすそう」という雑感をチームメンバーに共有しました。もっとも、開発期間最初の数日は自分のタスクが少なくて暇だったから作ってみたというのもあります。
素材は以下のサイトを利用させていただきました。
- みんちりえ( https://min-chi.material.jp/ )
- ぴくらいく( https://piclike.net/ )
チーム会での発言
週2回行われていたチーム会ではとにかく喋ることを意識しました。とりあえず誰かが喋っていればそれに呼応する形で話が進んでいくことがあるので、あまり深く考えずに口を開くことにしていました。ただ、逆に意味不明な発言をして場が「???」となることも多かったです(泣)。
ほかにも開発期間中に毎日行っていたチーム会ではそれぞれのタスクの進捗について気を配るようにしていたので、問題が発生すれば早めに共有できる空気を作ることができたと思います。
ツール導入の提言
GitHubのissuesとprojectsを使ってタスク管理と進捗管理をしようと提言しました。今回の開発で有益であることはもちろん、実務で使っているところもあると思うのでその練習という趣旨もありました。このおかげかは定かではありませんが、うっかり作業が重複してしまうことはなかったはずです。
関連技術の調査
有益そうなAPIやライブラリを調べて試してみるということもやっていました。ゲームを作るならcanvas APIやPhaserを使うと良いという情報を得たのでそれを使って簡単なゲームを作ってみたりしました。ただ、目的のノベルゲームにはややオーバースペックな気がしたので導入には至らず。
他にもゲームだからScratchやUnityはどうだろうと思ってこれらにも触れてみましたが、少し触った段階で「あ、これ違うやつだ」と気づいて不採用になりました。
ティラノビルダーというノベルゲーム開発ツールは使えそうな気もしましたが、こちらはプログラミングの知識がない人向けのツールだったので、わざわざ使う必要はないだろうということになりました。
結局のところ採用にいたった技術はなかったので無駄足になってしまったのですが、効率的な技術を調査するのは重要なので、こういう視点は忘れてはいけないと感じています。
環境構築
大した作業ではないのですが、メンバーが使っているPHPのバージョンからどのバージョンのLaravelを使うか検討し、環境を統一するための手順をまとめて共有しました。
オブジェクト指向
正直なところ5分のプレゼンで紹介できることは限られているので、オブジェクト指向を意識した設計は必須というわけではないのですが、オブジェクト指向でコードを書くスキルはいつか習得しなければならないので、いい機会だからやってみようとことで強く意識していました。
プレゼン後の拡張
チーム開発が終わった後、設計したクラスがちゃんと拡張性を意識できているのかを確認するために未実装の機能を実装してみました。プレゼンは終わっているのでただの自己満足なのですが、かなり容易に拡張できることが確認できたのでよかったです。
6. 反省点
5-2で触れたミニプロダクトについて、本当は開発期間の前にやっておくべきでしたが、他の作業があったので着手できず。事前にこれができていたら開発期間の冒頭からもっとスムーズに進んでいたような気がします。
あと、これは設計段階からの話ですが、1週間という開発期間を考慮せずに本気でゲームを作るという思考になることが多く、到底消化できないような量のタスクや複雑な仕様を提案するなど、会議の方向をおかしくしてしまうこともありました。さらに、評価されにくいオブジェクト指向設計についてもやけに力を入れてしまったので、チームメンバーからは「優先順位違うでしょ…」と思われていたでしょう。申し訳ありませんでした。 って書いたけど勉強になったからぶっちゃけ本気で申し訳ないとは思ってないよ!あはははははは!
ついでに反省すべきかどうかは微妙ですが、チーム開発に熱が入り過ぎて個人のオリジナルプロダクトをかなり後回しにしてしまっている部分があります。前述の通り、必要ない作業まで無意味に凝ってしまうことが多かったのでリソースの配分は考える必要があったでしょう。
7. チーム開発を経て得たこと
どうやってやったらいいのか見当がつかないことでも「とりあえずやってみます!」と言って引き受けておけば成長の機会が得られるので、案外これは良い方法なのかもしれないと学びました。もちろんチームの迷惑にならない範囲で。
あとは個人でのオリジナルプロダクトを作っているときよりもチーム開発をしているときのほうが充実感が大きかったことは意外な発見でした。
ついでに完全な余談ですが、ラスト2日間は徹夜でした。ずっと体が揺れている感覚があったのと、日付の感覚がおかしくなってタイムスリップした気分になりました。ちょっと面白かったです。
8. おわりに
プロダクトのアイデアについて、思いついたときは「ひらめいた!」ってなったのですが、途中から「あれ?これ面白いか…?」となって不安になることもありました。プレゼン後のフィードバックではまあまあ好評だったので結果オーライではあるのですが、自分の中で謎にアップダウンが激しかった印象があります。
評価されたのはUIデザインなど見た目部分のことが多く、デザイン周りはほぼ触っていない自分としては少しだけ徒労に感じた部分はありますが、かなり勉強になったので個人的には良かったです。チームの「縁の下の力持ち」になれてたらいいなあ。