※ [ディレクターズ・カット版]と書かれたスライドが、この記事を公開するにあたり追加したものです。
※ この記事には多くの画像が貼れれているため、読み込みに時間がかかる可能性があります
ゲーム開発初心者が教えるブラウザゲームのつくり方
まずは、自己紹介からさせていただきます。
2015年末にSIerからフロントエンドエンジニアにジョブチェンジして、さくらインターネットに入社しました。
いまは、さくらのクラウドのネタ機能開発や、自社サービスのエゴサを主な業務としています。ですので、みなさんがツイートされた内容はすべて目を通しています!
また、弊社では「さぶりこ パラレルキャリア」という副業を推奨する制度があり、それを利用して今年の1月からスタートアップ企業でVue.jsをいじっています。
今日の勉強会を開催するきっかけとなった「さくらのINFRA WARS」では、主にゲームの企画・デザイン、プロトタイプ開発、サウンドデザインを担当いたしました。
[補足]
ネタ機能については、「遊び心を実現する技術」と「リリースする度胸」の記事を参照ください。
最初に、ざっくりエイプリルフールでリリースした「さくらのINFRA WARS」というブラウザゲームについて紹介してから、シンプルなブラウザゲームのつくり方を発表します。
ゲーム開発初心者である私が、ブラウザゲームをつくるまでに学んだことや、ゲームの仕組みなどを具体的な実装例を交えて発表します。
最後に、「さくらのINFRA WARS」のサウンドデザインについても発表します。
今日の発表は、「ゲーム開発に興味がある人」「ゲーム/アニメーションをつくってみたい人」をターゲットにしています。
私自身、ゲーム開発初心者ですので、バリバリのゲームエンジニアの方には物足りないかもしれません。そういう方は、次のtownewgokgokの発表(「さくらのINFRA WARS」で 利用されている技術)にご期待ください!
また、この発表を通じて、みなさんがゲームの基本的な仕組みを理解し、実際につくってみたくなることを目指しています。
あとは、さくらインターネットにも「フロントエンドエンジニア」がいることを知っていただき、私たちと一緒に働きたいと思ってもらえればと思います。
さくらのINFRA WARSの紹介
このゲーム、知っているよ!または遊んだよ!という方はいらっしゃいますか?
(半数くらいが挙手)
これが、さきほどから名前がでている、「さくらのINFRA WARS」というブラウザゲームです。
また遊んだことないよという方は、2018年6月末までオフライン版を公開していますので、ぜひダウンロードして遊んでみてください。
さきほどの画像でなんとなく「さくらのINFRA WARS」がどんな感じのゲームなのかわかっていただけたかと思いますが、もうちょっと詳しい説明をいたします。
ジャンルは「インフラエンジニア育成型サーバー防衛シミュレーション」で、シンプルにいうと攻撃しない防衛特化型の逆シューティングみたいなゲームです。
プレイヤーがインフラエンジニアとなり、サイバー攻撃から身を挺してサーバーを守るという内容です。
[ディレクターズ・カット版]
このゲームのアイデアは、2017年9月ころに思いつきました。
さくらインターネットに入社して以来、さくらのクラウドのエイプリルフールのネタ機能の開発を担当してきました。
これは会社からいわれたものではなく、「自分のやってみたいこと」を「エイプリルフール」という口実を使ってやっているだけです。
そして、2018年はどうしようかと考えていたときに、ちょうどCanvasAPIを使った機能を実装しており、応用でインフラエンジニア向けのゲームは作れないかと思ったことがきっかけです。
ですが、前職からずっとアプリケーション開発がメインのため、インフラエンジニアの仕事についてよく知りません。
サイバー攻撃なんて、完全に攻殻機動隊の世界のイメージしかないので、たぶん「サイバー攻撃をされたらバリアを張って守っているんだろうなー」、「サーバーが攻撃を受けたら炎上して爆発するんだろうなー」という、私の中の雑なインフラエンジニア像をもとにゲームのアイデアを練っていきました。
[ディレクターズ・カット版]
ゲームのルールはこんな感じです。簡単なルールですので、実際に遊んでいただければすぐ理解していただけると思います。
[ディレクターズ・カット版]
そんな感じでプロトタイプを開発して、Slackのさくらのクラウドの企画チャンネルに投稿してみたところ…
[ディレクターズ・カット版]
なんか知らないうちにすっごい進化していましたw
どうやら弊社Slackには「何か」が住み着いているようですw
[ディレクターズ・カット版]
ただ、私はプロトタイプ版までしか作っていないので、それをベースにシンプルなブラウザゲームの開発方法についてこれから発表していきます。
シンプルなブラウザゲームのつくり方
ここからようやく本編です。ゲーム開発初心者である私が、ゲーム開発するまでにしたことや、ゲームの簡単なしくみを具体的な実装例も交えて説明していきます。
そもそもゲームはどうやってつくるのか?
私の戦いはここからはじまりました。
ちなみにみなさんはゲーム開発についてどんなイメージをお持ちですか?
私が持っているゲーム開発のイメージはふわっとしたもので、C++やC#+Unityを使って開発するとか、数学や物理の知識が必要とか、ドット絵とか3Dとかグラフィックをつくるのが大変そうとか、NEW GAME癒やされるよねとか。。。
全体的に難易度Very Hardなイメージがありました。
難しそうなので、最初から製品版クオリティを目指すと絶対挫折すると思ったので、シンプルで開発環境構築もほとんどいらず、ブラウザで簡単に実行できるゲームをつくろうと思い勉強をはじめました。
すぐ開発を始められればよいのですが、そもそもゲームのつくり方がわからないので、
まずはじめにしたことは「JavaScript game」でググることです。
そこで出てきた、W3Schoolsのゲーム開発チュートリアルをやりました。CanvasAPIの使い方やコントローラ、衝突判定などの実装方法がかかれています。
次にCanvasについてもっと知りたかったのでMDNのCanvasチュートリアルを一通り読みました。有志により多くのページが日本語化されていますので、英語が苦手な方でもスラスラ読めると思います。
2つのチュートリアルが終わって早速ゲーム開発をしようと思ったのですが、複数オブジェクトの管理やタイムの管理方法がわからなかったので、既存のゲームエンジンをちょっとだけ流し読み参考にさせていただきました。
phina.jsとenchant.js、どちらも日本人が開発したライブラリですので、日本語情報が多く読みやすかったです。個人的にはphina.jsがオススメです。
チュートリアルをやってゲーム開発について「あーそーゆーことね、完全に理解した」ので、
そんな「ゲーム開発を完全に理解した」私が、ブラウザゲームのつくり方についてお教えします。
ゲームの大まかなしくみは、ループです。
ループの中で、ユーザーの入力を受け付けたり、座標を更新したり、衝突判定をしたり、レンダリング処理を行います。このあたりは順不同ですが、大まかにはこんな感じでゲームが動いています。
[ディレクターズ・カット版]
プロトタイプ開発をしたときは、このようなクラス設計にしました。
BaseItemクラスに座標やサイズ、衝突判定で使う位置を定義し、それを継承してPlayerクラスやBeamクラスをつくりました。それぞれのクラスでは、座標を更新するためのupdateメソッドや、オブジェクトを描画するためのdrawメソッド、衝突検知したときの処理をするhitメソッドをオーバーライドします。
それらのItemクラスをコアとなるGameクラスに集約し、ループやユーザー入力を受け付けます。
[ディレクターズ・カット版]
さきほどのクラス図を簡単にまとめるとこんな感じです。
全体像については説明しましたので、次からは具体的な実装方法について解説していきます。
まずはゲームの基礎であるループ処理からです。
一般的にゲームでは1秒間に60回という一定間隔でループ処理が実行する必要があります。
ちょっと語弊はありますが、JavaScriptには一定間隔ごとに実行するためのメソッドが3種類あります。setTimeout、setInterval、requestAnimationFrameです。
このなかでゲーム開発にはrequestAnimationFrameがよく使われます。
理由としては、setTimeoutやsetIntervalは実行間隔を指定できるのですが、ブラウザの状況におかまいなく指定時間間隔で実行されてしまいます。そのため、ブラウザに負荷がかかって処理が遅延しだしたとき、前のループ処理が終わっていないのに次の処理が走ってしまい、バグや画面のチラツキなどの元になります。
対して、requestAnimationFrameは、ブラウザの状況に応じて実行間隔が自動調整されます。基本は60fpsですが、負荷がかかったり、ブラウザがバックグラウンドにいったりするとフレームレートを自動的に調整してくれます。
モダンブラウザはすべて対応していますので、好んでIE9対応をしたい方以外は、requestAnimationFrameを使うことをオススメします。
しかし、requestAnimationFrameにも欠点があります。それが「実行間隔を自動調整してくれる」という点です。
わかりにくいかもしれませんが、gifアニメーションをよく見てみてください。違いがわかりますか?
「フレームスキップしない」方は、オブジェクトが止まってから動きはじめるまでずっと同じ場所にいます。このように故意にブラウザに負荷をかけてオブジェクトを止めたり、ゆっくり動かすことができてしまいます。
その対策をしたのが、下の「フレームスキップする」です。
こちらは止まってから再度動き出すとき、止まった場所からではなく、先から動きだしています。何をしているかというと、
ゲーム内の時間を進めてフレームスキップをしています。
requestAnimationFrameのコールバックには、呼び出し時の高精度な時間が渡されます。60fpsの場合、その時間と前回実行した時間差は16.66ms(1000msec/60frame)であるべきなので、それより差が大きい場合は処理が遅延していることを意味します。処理が遅延したということは、座標の更新処理などが通常より少ない回数しか実行されていないということです。
そのため、16.66msの差を埋めるために溜まっていた座標更新などを行い、ゲーム内時間を進めています。これでrequestAnimationFrameの欠点が解消されました。
後編に続く
関連記事
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿