DNEK's blog

Sounds like "dee-neck". 「でぃーねっく」と読みます。

「にじぷよ」開発記

この記事はKMC Advent Calendar 2021 - Adventarの22日目(12/22)の記事です。

adventar.org

21日目の記事は、StrelkaさんのGAN(画像生成)で遊んだ話 - strelka_dogのブログでした。

strelka-dog.hatenablog.com

目次

はじめに

KMC9年目のdamaです。 Twitter等ではDNEK(でぃーねっく)と名乗っています。

昨年までの6年間、毎年12/6にKMC Advent Calendarの記事を書き続けていたのですが、今回は都合により後ろの方の枠を取りました。

今年の夏に「にじぷよ」というゲームを作ったら思いの外流行ったので、その話をしようと思います。

「にじさんじ」を知らないと楽しめないかもしれませんが、一応こちらで遊べます。 記事を書くついでに、本日ユニットの追加更新をしました。

nijipuyo.dnek.net

なお、この記事は技術的な知識が無い人でも読めるような構成にしているはずですが、分かりにくい部分があればコメントやTwitterでご指摘ください。

すべてのはじまり

今年の6月12日、かの有名なバーチャルライバーグループ「にじさんじ」に所属している鷹宮リオンさんが、以下のようなツイートを投稿しました。

翌日、それに対してイラストレーターの白井さんがコンセプトアートを提示し、鷹宮さんが引用ツイートしたことで注目を集めていました。

同日深夜、一連のツイートに気付いた私は、「これ実装したらワンチャン遊んでもらえるのでは」「名前を売るチャンスか?」「にじさんじ(推しグループ)の鷹宮さん(推し)に遊んでもらえるだけでも普通に嬉しい」「『ユニット多過ぎてすぐ消えそう』って言ってる人達をわからせたい」などの動機により、製作を検討することにしました。

製作検討

翌14日昼頃、以下の点について真面目に検討をしました。

製作するメリット

  • 名前を売れる

個人開発で生計(?)を立てている身として、自分の名前を広く知ってもらうことは大事なはずです。 おそらく人気VTuberのアイデアをある程度のクオリティで形にできれば、それなりの宣伝になるでしょう。

  • 勉強になる

クリエイターたるもの、手を動かすことは何よりも尊いことです(ちゃんと勉強もしましょう)。 特に、話題に便乗して開発するということをしたことがなかったため、良い経験になると思いました。

  • 承認

私は普段からVTuberの配信を見ており、特に「にじさんじ」を箱推ししています。 比較的広く浅いタイプのオタクではありますが、鷹宮さんは「にじさんじ」の中でも特に好きなライバーの1人です。 その鷹宮さんのアイデアを形にし、あわよくば遊んでもらうことができれば、何物にも代え難い承認を得ることができるでしょう。

以上より、「にじぷよ」を作るメリットは十分にありそうです。

製作するデメリット

  • 収益化が難しい

個人開発で生計(?)を立てている身として、自分の作品・労力をお金にすることは大事なはずです。 とはいえ、他者の著作物を二次利用する以上、収益化については慎重になる必要があります。 幸いにも、にじさんじを運営するANYCOLOR株式会社は「ANYCOLOR二次創作ガイドライン」というものを策定しており、これに則れば比較的安心して二次創作活動をすることが可能なはずです。

event.nijisanji.app

そして本ガイドラインの第6条1項によれば、

コミックマーケットやインターネットを利用した同人誌や二次創作グッズの販売等のうち、みなさまの趣味の範囲内の活動であれば、本コンテンツの二次創作作品を販売することはできます。しかし、その販売行為を、ファン活動を超えた事業活動として行ってはならないものとします。

ということらしいです。

また、同条第2項には、

その販売行為が、前項の事業活動に該当するかどうかは、当社が作品の生産数量、販売価格、作品の性質等の諸要素を総合的に判断して決します。

とあります。

ゲームってどうなんでしょうか? おそらく「にじぷよ」を収益化する場合、ブラウザゲームとしてAdSenseなどの広告を貼る形態になると思いますが、少なくとも既存の「にじさんじ」ファンゲームで広告を貼っている例は見当たりません(見逃しているかも)。

wikiwiki.jp

ここは慣例に従い、収益化はしないこととしました。

収益化ができなくとも他に大きなメリットがあるので、特に製作を控える要因にはならないでしょう。

プラットフォーム

プラットフォーム、すなわちプレイヤーが遊ぶ環境というのは重要です。 おそらくPCソフト、モバイルアプリ、ブラウザゲームの3択になると思いますが、ここはブラウザゲーム一択だと判断しました。

まず、無名のミニゲームを広く浅く遊んでもらうには手軽さが大事です。 URLからリンクを開くとすぐにプレイできるのが一番抵抗が少ないでしょう。

そもそもPC・モバイル双方のプレイヤーが居ることが予想されるため、いずれの環境でも動作するブラウザ向けに作るのが一番コスパが良いです。

また、特にモバイルアプリを公開する場合、一般的にはPlayStoreやAppStoreといったストアで公開することになります。 今回はかなりスピード感を重視しているため(後述)、審査などに時間を取られるのは避けたいところです。

そして、既存のファンゲームもほぼブラウザゲームです。 プレイヤー側もそのような意識があるでしょうし、ここも慣例に従いましょう。

競合

さて、先程の各ツイートへの引用ツイートを見ていると、何人か「作ろうかな」と言っている方々がいることが分かります。 また、私のように黙って作り始めようとしている方もいたことでしょう。 ネタ被りは仕方ないことですが、なるべく予想を立てておきたいところです。

ここでまた既存のファンゲームを引き合いに出しますが、これらの多くに比べるとややロジックが複雑になりそうです。 とは言え、ぷよぷよに少し毛が生えた程度のシンプルなゲームにも思えます。

……本当でしょうか? 結論だけ言うと、ユニットが揃っているかどうかを判定するためには、ぷよぷよとは比較にならない高度なアルゴリズムが必要です。 なお、このアルゴリズムの話だけでも十分面白いと思うので、後日別の記事を書いて解説しようと思います。

さて、正直に言って「ツイートを見て作りたいと思った」「ゲームをすぐに実装できる」「ユニットマッチングアルゴリズムをすぐに考えられる」という条件をすべて満たしているのは自分くらいしか居ないのではという気がしてきました。 むしろ「私が作らなければ鷹宮さんの素晴らしいアイデア、白井さんのコンセプトアートが活かせなくなってしまう、これはもったいない!」という使命感さえ生まれてきました。 競合などと考えている場合ではありません。

ゲームバランス

鷹宮さんのアイデアは素晴らしいものですが、そもそも実際に作ってみたものがゲームとして成り立つのかは疑問です。

開発当時の現役ライバーは102人おり、それに対するユニット数は480組程度でした。 そのうち比較的揃いやすいと思われる二人組ユニットが約250組です。 単純に計算すると102人から2人を選ぶ組み合わせは {}_{102} C_2 = 5151 通り、つまり適当に2人を隣り合わせてユニットが揃う確率は約20回に1回程度です。 実際にプレイされた方なら分かるかと思いますが、これは結構難しいです。 ゲームとして面白くなければ、果たして作る意味はあるのでしょうか?

とはいえ、実際に作ってみなければ分からないし調整もできません。 それに、話題に便乗したネタゲーとして「無理ゲーw」とでも反応してもらえれば十分満足です。

なお、この予想は良い意味で裏切られ、また、鷹宮さんの次なる天才的アイデアにより更に改善されることとなりました(後述)。

開発フレームワーク

ここはゲーム開発に興味の無い方は飛ばしてもらって良いです。

毎度登場、既存のファンゲームですが、ほとんどがRPGツクールかUnity製です。 今回作るのはアクションパズルゲームであり、RPGツクールは使わないでしょう。 となると、定番にして万能(?)のゲームエンジンUnityを使いたくなりますが、主にブラウザゲームに使われるUnity WebGLはモバイルデバイスをサポートしていないようです。

docs.unity3d.com

実際にはモバイルでも動作する場合があるようですが、公式にサポートされていない以上、採用には不安があります。

ここで「にじぷよ」の開発要件を振り返ってみると、グラフィックはシンプルな2D画面で十分そうで、肝となるロジックの実装は特に言語を選びません。 それなら普通にHTMLとJavaScriptで書くのがオーバーヘッドも少なく無難そうです。

とは言え、ゲームエンジンを自作するような暇は無いのでJavaScript製のゲームエンジンを使いたいです。 人気・無料・OSS・コミュニティが活発という条件で探したところ、Phaser3一択でした。

phaser.io

github.com

折角npmにも対応しているので、yarnでパッケージ管理してTypeScriptでコーディング、webpackでバンドルすることにしました。 なお、yarnもTSもwebpackもまともに使うのは初めてだったのですが、果たして本当にスピード感を重視して作る気があったのでしょうか……?

ホスティングにはとりあえずGitHub連携が楽なNetlifyを使っていました(後日Firebase Hostingに変更)。

イラスト素材

ぶっちゃけこれが一番の懸念事項でした。 私は大して絵が描けないし、描く時間も無いので、各ライバーの公式画像を流用するか、誰かにイラストを依頼するしかありません。

依頼するとなると、当然注目を集めていた白井さんが理想です。 が、そもそもコンセプトアートを描いたからといって、実際のゲーム製作にまで興味があるとは限りません。

気になってツイートを遡ってみたところ、以下の引用ツイートを見つけたのでこれはクリアとします。

ただ、それよりも大きな懸念があります。 果たして、こんなどこの馬の骨とも知れない無名個人開発者が唐突に依頼したところで話を聞いてもらえるのでしょうか?

……これはもう、実力でカバーするしか無いでしょう。 つまるところ、最低限動作するプロトタイプを作り、それを見せた上で依頼します。 あとは絵を入れればリリースできそう、という状態を示せば、信用してもらえる可能性は高まるのではないでしょうか。 なお、見せるためには何かしらの絵が必要なので、一旦各ライバーのYouTubeアイコンで代用しました。

もし断られても、このYouTubeアイコンのままリリースするつもりでいました。

製作期間

開発工程がだいぶ具体性を帯びてきたところで、最後にスケジュールを考えます。

話題に便乗する以上、なるべく早くリリースしたいです。 1ヶ月もすれば忘れ去られてしまうかもしれません。 白井さんに絵を描いてもらえる場合はプロトタイプを見せてから描いてもらうことになるので、なおのこと急ぐ必要があります。

自分のポテンシャルを信じ、プロトタイプは(鷹宮さんのツイートから)1週間で作ることにしました。

製作過程

こうして無事に製作決定したのが6月15日になります。 6月16日から作業を開始しました。

プロトタイプ

気合いと根性により、なんとか6月19日までに以下のような最低限動くものを作ることができました。

にじぷよプロトタイプ

画面はローディング→タイトル→プレイ画面のみです。 ユニットマッチの演出、NEXTぷよや一時停止もなく、おまけにユニットマッチングアルゴリズムにバグがあるのですが、とりあえずプレイできるので良しです。

余談ですが、私が開発・運営している「v-data」というVTuber検索サイトが少し役に立ちました。 「にじさんじ」の記事で所属ライバーがYouTubeアイコンと共に一覧されているのですが、これらをドラッグ&ドロップすることで画像素材の準備が捗りました。

v-data.info

依頼

同日深夜、「突然失礼いたします」云々というDMを白井さんに送りました。 翌20日昼頃、予想に反してすんなりと快諾いただき、すぐにスケジュール調整に移りました。

https://i.gyazo.com/48e34df0aadd8590371ac9ecebb759d5.png

お忙しいにも関わらず1週間で用意していただけるとのことで、ほぼニートな生活をしている私が遅れを取るようなことがあってはならない、と俄然気合いが入っていた気がします。

本製作

機能追加

プロトタイプではプレイに最低限必要な機能しかありませんでしたが、公開に向けて以下のような機能を追加しました。

  • 得点機能
  • 一時停止
  • NEXTぷよ
  • ユニット一覧

とりあえず得点機能についてだけ細かく説明しておきます。

得点調整&演出

具体的な得点の出し方については、私とテスター(友人)の体感で決めました。 ゲーム内の「遊び方」説明では分かりやすいように具体例しか載せていませんが、一般化した点数は以下のようになっています。

  • 人数点: N 人組が揃うと {10} \times {3}^{N - 2}( N \geq 2 )
  • 連鎖点: N 組目が揃うと {10} \times {2}^{N - 2}( N \geq 2 )
    • プレイヤーの操作が終わってから次の操作までを連鎖とする

また、得点時の演出を考えるのには意外と苦労しました。 最初は「4人+90 3連鎖+20」のように表示しようとしたのですが、演出に使える時間が短いため、ユニット名の表示と合わせると情報量が多くてとても読めません。 そこで「ぷよぷよeスポーツ」を参考に「N連鎖」の形にしてみましたが、まだ煩かったため、最終的に「×N」という形に落ち着きました。 他にも後ろのUIを半透明にしたり、文字の位置を細かく調整したりなど、実はかなりこだわっています。

白井さんとのやり取り

イラストを描いていただくにあたり、実際のゲーム画面での見え方を確認しながら描けると便利だろうと思いました。 そこで、描けたものから何枚かずつ提出していただき、都度テスト環境のYouTubeアイコンと差し替えるようにしました。 これも先にプロトタイプを作っていたからできたことだと思います。 そしてスケジュール通り6月27日深夜には全員分を提出していただけました。

また、白井さんから「背景にグリッドがあると見やすいかと思う」という提案をいただき、市松模様を追加しました。 実際、↑のプロトタイプに比べてだいぶ見やすくなったと思います。

更に、OGP画像(Twitter等でURLを共有したときにサムネイルとして出てくるやつ)のデザインもしていただきました。

公開

そんなこんなで6月28日の昼頃にはリリースできる状態になり、19時ジャストにツイートで公開しました。

鷹宮さんの反応

#リオンあーとタグを付けていたお陰か、6分後という早さで鷹宮さんからリプライをいただきました。

正直、RTやリプライはいただけても配信でやってくれるかは分からないと思っていたので、すぐに採用していただけてとてもうれしかったです。

サーバー費用問題

さて、予想を遥かに超える人気が出て大変うれしいものの、人気だからこその問題も出てきます。

「にじぷよ」はFirebase Hostingというサービスによりウェブサイトとして公開されています。 各ユーザーがここのサーバーから「にじぷよ」のデータをダウンロードする仕組みになっています。

firebase.google.com

Firebase Hostingは1日360MBまでのデータ転送が無料という、小規模のウェブサイトに優しい仕様になっているのですが、「にじぷよ」のデータ転送量は初日だけで36.9GBに達していました。

Firebase Hostingのデータ転送料金は、無料分の360MBを除くと1GB当たり$0.15、大体17円くらいです。 つまり初日だけでサーバー代が600円くらい掛かっていることになります。

firebase.google.com

破産するというほどではありませんが、一日600円というのは貧乏個人事業主からするとバカにできない金額です。 また、今後鷹宮さんの配信が控えていることも考えると、もっと大変なことになるかもしれません。

とりあえず、我らがコンピューターサークルKMCのSlackで相談することにしました(ちなみにこの記事はKMC Advent Calendar 2021 - Adventarの記事です)。

www.kmc.gr.jp

最初は、データ量を減らすとかライブラリをCDNからダウンロードするようにするとか小手先の対策を考えていたのですが、もっと根本的な解決策を教えてもらうことができました。

Cloudflareです。

www.cloudflare.com

名前だけ知っていて使ったことはなかったのですが、なんとCloudflareは、Firebase Hostingと同じようにデータをダウンロードさせるだけなら無料で無制限にできてしまうのです。

www.cloudflare.com

また、Firebase Hostingとユーザーの間にCloudflareを割り込ませるという使い方(プロキシ)をすることもできます。 どういうことかというと、Firebase HostingくんはCloudflareくん1人だけにデータを転送しておき、Cloudflareくんが代理で大量のユーザーへデータを送ってあげるという仕組みです。

今回はこの設定の方が楽だったので、プロキシを採用しました。 こうしてFirebase Hostingの費用は余裕で無料の枠内に収まり、私の生活は守られたのでした。

にじぷよ、配信デビュー

公開から数日、続報が無いのでもしかして配信がお流れになってしまったのではと無駄な心配をしていた頃、7月1日夜の配信を視聴していると、

明日の夜かな?(にじぷよを)やろうかなって思っているところです

という突然の告知がありました(動画56:20〜)。

youtu.be

50人モード

また、その直後にもう一つ重要な発言がありました。 要約すると、

ライバーを100人じゃなくて50人くらい選んでやりたい、そしたらわりと簡単にできそう

とのことです。

配信まで1日しかありませんが、確かに良いアイデアだと思うし、鷹宮さんの提言とあらば実装しないわけにはいきません。

しかしながら、プレイヤーがプレイごとにチマチマと50人を選ぶというのは面倒です。 したがって、ある程度自動的に選ぶ仕組みが必要です。

ただし、ここで適当な選び方(ただのランダム等)を実装してしまうと、同じユニットのメンバーが居ない孤独なライバーが発生し、お邪魔ぷよとなってしまう可能性があります。 かと言って、揃えやすいライバーに偏るような実装をすると、揃えにくいライバーが滅多に出現しなくなってしまいます。

色々と考えた結果、絶対に出現させたいライバーを1人だけ選択する方式にしました。 こうすれば、推しが揃えにくいライバーだとしても、必ず出現させることができます。

あと49人はどうするかというと、まずそのライバーを含むユニット1組を自動的に選び、そのメンバーをまとめて出現リストに追加します。 ユニット単位で追加されたのですから、当然この段階で孤独なライバーは存在しません。 次も同じように、出現リストから1人選び、そのライバーを含むユニット1組を選び、メンバーをまとめて追加します。 これを約50人になるまで繰り返すことで、適切なリストが完成します。

なお、現在の実装では、最初に選んだライバーの所属するユニットがすべて揃うように修正しています。

こうして、なんとか配信1時間20分前に「50人モード」を実装することができました。

そして7月2日に配信された動画がこちらになります。

www.youtube.com

その後

鷹宮さんに配信でプレイしていただけただけでも大成功だと思っていたのですが、同日深夜に静凛さんがツイートをしてくださいました。

そして4日後には葉加瀬冬雪さんにも配信をしていただけました。

その後も続々とにじさんじライバーの方々によるにじぷよ配信が続き、それと並行して7月18日まで何度かアップデートを繰り返しました。

ここで、これらのアップデートの中でも反響の大きかった「巨大な得点」について解説します。

巨大な得点

こちらの動画が有名ですが、実は「にじぷよ」では1000回を超える連鎖が可能です。

www.youtube.com

#得点調整&演出で説明したように、にじぷよの得点は人数または連鎖数の増加に従って指数関数的に増加します。 例えば1000連鎖すると {10} \times {2}^{998} という非常に大きな得点になります。

この巨大な得点に対し、「バグったりオーバーフローしなくてすごい」というコメントやツイートをしている人が多く見られます。 これは一体何なのでしょうか?

最近の一般的なコンピュータは {2}^{64} - 1 までの整数を高速に処理できるようになっています。 パソコンを購入するときに「64ビット」や「32ビット」と書かれているのを見たことがあるかもしれませんが、この数字が関係していたりします。 逆にそれを超える整数の計算は効率が悪いし、使う機会もほとんど無いため、多くのプログラミング言語では巨大な整数の計算に標準対応していません。 無理に大きな整数を使おうとすると、誤差が生じたり一周回って小さい数字に戻ってしまったりします。 そのため、プログラミング経験のある人達が、巨大な整数を扱っていることに驚いていたのだと思われます。

しかし、標準対応していないのであれば誰かが作ったライブラリ(拡張機能)を使えば良いだけです。 また、効率が悪いと言っても「にじぷよ」で {10} \times {2}^{998} の足し算をするくらいなら余裕でできるのです。

ちなみに「にじぷよ」はJavaScriptというプログラミング言語で実装されています(本当はTypeScriptだけどこの話では関係ない)。 JavaScriptの標準的な数値計算では、 {2}^{53} - 1 を超える整数を扱おうとすると誤差が生じるとされています。 {2}^{64} - 1 ではありませんが、近い桁数です。

developer.mozilla.org

もっと大きな整数には、 BigInt を使用することを検討してください。

と書かれていますが、このBigIntという道具は少し古いiOSデバイスでは使えないなどの制約があります。

そこで、にじぷよでは「big.js」というライブラリを使わせてもらっています。

github.com

なお、コンピュータで扱う巨大な整数のことを「多倍長整数」と呼ぶことがあります。 興味がある方は以下の記事などで勉強してみると良いでしょう。

qiita.com

統計

実は「にじぷよ」では利用者数の統計を取っているので、最後に大まかな数字を紹介して終わろうと思います。

6月28日の公開から本日12月22日までのPV(ページ閲覧数)は約181万回、ユーザー数は約32万人だそうです。 また、1日当たりのユーザー数が最も多かったのは7月11日で、約2万6千人でした。 この頃に比べると流石に減ってはいますが、最近でも毎日1,500人くらいの方々に遊んでいただいています。

まとめ

「にじぷよ」は鷹宮リオンさんのアイデア、そして白井さんによる緊密な協力のお陰で作ることができました。 そして、その他多くのにじさんじライバーやプレイヤーの方々のお陰でここまで人気のゲームになることができました。 その人気によって破産することを防げたのはKMCのお陰です。

また、本文中では触れませんでしたが、にじさんじ内のユニットを把握する上で「にじさんじ非公式wiki」の「コラボ一覧表」が非常に役に立ちました。というより不可欠でした。 wiki運営や編集者の方々には頭が上がりません。

wikiwiki.jp

クリエイターとして貴重な経験を与えてくださった皆様に感謝いたします。

今後も不定期にユニットの更新をしていこうと思うので、時々遊んでいただけるとうれしいです。

ついでに

最近の私は、PC版「運ゲー排除マインスイーパー」というものを開発しており、近いうちにSteamで発売する予定です。 WindowsとMacに対応予定です。

ちなみにモバイル版「運ゲー排除マインスイーパー」は既に各ストアで無料配信されているので、良かったらプレイしてみてください。

また、「ニジウメ」という紛らわしい名前の漢字パズルアプリも出しているので、漢字に自信のある方はこちらもどうぞ。

本文中でも紹介したVTuber検索サイト「v-data」もよろしくお願いします。

以上、長文にもかかわらず最後までお読みいただきありがとうございました。

次回のKMC Advent Calendar

明日のKMC Advent Calendar 2021 - Adventarの記事はwalkureさんの予定です。