概要
以前作成した音ゲーのWEBアプリ版のレシピを公開したいと思います。 フレームワークはcocos2d-JS、言語はCoffeeScriptを使用します.
cocos2d-JSとは?
cocos2d-JSはオープンソースの2DゲームフレームワークのJavaScript版です。JavaScriptでiOS、Androidの両方に対応したアプリが作れます。また、WEB用にビルドすることでブラウザ上で動作するアプリを作ることも可能です。 以下は公式のデモですが、スマホのブラウザ上でもヌルヌル動くことが確認できると思います。
Cocos2d-html5 Show Case - MoonWarriors
CoffeeScriptとは?
JavaScript のコードに変換されるAltJSの一つです。 概要は以下の記事を参照してください。
どんなゲーム?
『ノート』が曲に合わせて落ちてきます。『ターゲット』に重なるタイミングでタッチしてください。
完成品
こんなんです。
Cocos2d-html5 Hello World test
準備
node.jsのインストール
CoffeeScriptやGulpを使用するためnode.jsをインストールします。
公式ページからダウンロードしインストールしてください。
Macの場合、Homebrewを使ってインストールすることも可能です。 以下のコマンドでバージョンが表示されればインストール完了です。
node -v
Gulpのインストール
GulpはCoffeeScriptのコンパイルや結合などに使用します。 以下のコマンドでインストールできます。
npm i gulp -g
cocos2d-JSのインストール
以下の記事を参考にインストールしてください。 現在のcocos2d-JSのバージョンは3.6です。 記事はwindows環境での作業になっていますが、macでも同様です。 基本的にはcocos2d-JSをダウンロードし、setup.pyを実行すればOKです。 記事後半の「coffeescriptへの変換」は不要です。
プロジェクトの作成
今回作成するサンプルプロジェクトを作成します。 以下のコマンドを実行してください。 「flava」がプロジェクト名になります。
cocos new flava -l js -d .
完了後、「flava」ディレクトリが作成されていると思います。
ディレクトリ内のmain.js
、src/app.js
、src/resource.js
を削除しておいてください。
次に、以下のzip解凍し、中身を「flava」ディレクトリへコピー・上書きしてください。
https://github.com/bokuweb/cocos2d-JS_skeleton/archive/gh-pages.zip
「src」ディレクトリ内にapp.coffee
、main.coffee
、resource.coffee
が、ディレクトリのトップにgulpfile.coffee
、package.json
が格納されていればOKです。
プロジェクトの動作確認
以下のコマンドを実行してください。
npm i
その後、以下のコマンドを実行してください。
gulp build:coffee gulp watchify
正常に完了すればディレクトリのトップにmain.jsが生成されます。
次回以降gulp watch
を実行することにより、src/*.coffee
に変更があるたびに自動的にmain.jsが生成されます。
ctrl
+c
で終了できます。
試に動かしてみます。 以下のコマンドを実行してください。
cocos run -p web
cocs2d-JSはディレクトリトップのmain.js
を実行します。
ブラウザが起動し、以下のような画面が起動すれば動作OKです。
リソースの用意
今後使うことになる画像等のファイルをダウンロードして./res
に放り込んでおいてください。
ファイル名 | 説明 |
---|---|
Ouroboros.mp3 | 今回プレイする音楽ファイル |
bg.jpg | 背景画像 |
cover.jpg | 音楽カバーイメージ |
note.png | ノートイメージ |
dest.png | ターゲットイメージ |
ディレクトリについて
いろいろディレクトリがありますが基本的には触るのはres
とsrc
です。
ディレクトリ名 | 説明 |
---|---|
res | 画像等のリソースを格納する |
src | ゲームのソースファイルを格納する |
srcの中には現在以下のようなファイルがあると思います。
ファイル名 | 説明 |
---|---|
main.coffee | main。まずはこいつが実行される |
resource.coffee | 画像等のリソースファイルを管理する |
app.coffee | アプリ部分 |
ブラウザのキャッシュをOFFにしておく
開発中はブラウザのキャッシュをOFFにしておいたほうがよいです。
chromeの場合デベロッパーツールの設定でDisable cache (while DevTools is open)
にチェックを入れておくとよいです。
デベロッパーツールを開いている間のみキャッシュOFFになります。
手順1. 背景を表示してみる
※各ファイルの変更前にgulp watch
を実行しておいてください。
変更後に以下のようにしてもOKです。
gulp build:coffee gulp watchify
main.coffeeの変更
まずはmain.coffee
を編集します。
5行目でapp.coffee
をrequireしています。いつまでもHelloWorldScene
じゃおかしいのでGameScene
にリネームします。
同様に14行目もGameScene
にリネームします。
次に11行目を次のように変更します。
cc.view.setDesignResolutionSize 320, 480, cc.ResolutionPolicy.SHOW_ALL
これはどんな解像度の端末であれ「横320px×480pxで描画しますよー」という仮想的な解像度です。
この設定により端末による差異をなくし、同じように表示することができます。
cc.ResolutionPolicy.SHOW_ALL
は縦横比を保ったまま、はみださないように端末にフィットさせる設定です。
他にも縦横比を無視して画面にフィットさせる設定や、縦横比を保ったまま短い辺に合わせる(長い辺ははみだす)設定などがあります。
13~15行目でリソースのプリロードを行い、プリロード完了のコールバックでGameSceneに切り替えています。
cc.directorは名前の通りでゲームのシーンなどを管理します。
cc.director.runScene new GameScene()
でシーンをGameSceneに切り替えています。
21~25行目ではGameScene
を定義し、GameScene
にGameLayer
を追加しています。
cocos2dでは『シーン』と『レイヤー』の概念があり、『スプライト』や『ラベル』をレイヤーに追加し、1つ以上の『レイヤー』を追加することで『シーン』を構築していくのが基本っぽいです。
・変更後 main.coffee
resource.coffeeの変更
resource.coffee
は画像などのリソースを管理します。
画像などを使用する場合は必ずこのファイルに追記する必要があります。
ついでに今後使用する予定のリソースをすべて追記しておきます。
何か独自に使用したい画像などがあれば現在のフォーマットに習って追加すればOKです。
・変更後 resource.coffee
これで背景画像bg.jpg
を使用することができます。
app.coffeeの変更
main.coffee
と同様HelloWorldScene
をGameScene
にリネームします。
1行目でresource.coffee
をrequire
しています。
5行目のctor
はコンストラクタです。new GameLayer()
としたときに実行されます。(ここでは24行目ですね)。
ここでは"Hello World"を表示するラベルと背景画像の設置を行っています。
14行目~19行目が背景画像配置処理です。
15行目でアプリサイズの取得。
16行目で背景画像bg.jpg
を使用したスプライトを生成しています。cc.Sprite.create "画像へのパス"
でスプライトは生成できます。
17~18行目でスプライトをアプリの中央に配置。
19行目でGameLayer
に追加しています。addChild
の第二引数はzIndex
すなわちZ方向の表示順序です。
この場合"0"なのでGameLayer
の最奥に配置され、"1"や"2"に設定されたスプライトやラベルの方が手前に表示されます。
・変更後 app.coffee
実行してみる
cocos run -p web
ブラウザが起動して以下のようになればOKです。
手順2. タイマークラスの実装
timer.coffeeの追加
cocos2d-JSでは残念ながらBGMの再生時間を取得することができません。 なので、自身でタイマを作成し再生時間を計測する必要があります。 タイマークラスは以下のようにしました。srcに追加してください。
・timer.coffee
start()
でタイマーを開始し、get()
で開始からの経過時間を取得します。
手順3. タッチ(クリック)できるスプライトの実装
通常のスプライトはタッチ(クリック)しても何も反応しません。 今回のゲームはタイミングよく『ノート』にタッチするゲームなのでタッチできるスプライトを作る必要があります。 以下のようなTouchSpriteクラスを作成します。
touchSprite.coffeeの追加
3行目の@_super
は継承元(この場合cc.Sprite
)の同名のメソッド(この場合ctor
)を呼び出しています。
すなわちcc.Sprite
のコンストラクタctor
にスプライトに張り付ける画像を渡しています。
4~8行目でタッチベントを登録しています。8行目でタッチ開始時に呼ばれるメソッドを登録しています。
10~17行目はタッチ時の処理です。
ただし、11行目~15行目はひとまずおまじないと思ってもらっていいと思います。
タッチされた領域が一致しているか比較してるっぽいです。
なのでタッチされたときの処理は16行目以降にif
の中に書けばいいです。
・touchSprite.coffee
手順4. タッチスプライトを継承しノートクラスの実装
note.coffeeの追加
手順3で作成したタッチスプライトを継承し『ノート』クラスを作ってみます。 『ノート』の動作は以下です。
- 設定した時間に設定したY座標(ターゲット)に到達するように移動する
- タッチされず一定時間経過した場合はフェードアウトする
- タッチされた場合、設定時間とタッチされた時間との差分を計算し、判定を行いリスナーに通知する
これらを実現していきます。
5~7行目はコンストラクタです。 第一引数でテクスチャ、第二引数で各種パラメータ、第三引数でタイマーを受け取っています。 パラメータの内容は目標Y座標、目標Y座標に到達する時間、落下速度、判定しきい値です。
6行目でTouchSprite
にテクスチャを渡しています。
7行目の@_listeners
イベント(今回は判定イベント)が発生したときに実行するコールバックを保持する配列です。初期化しています。
9~10行目は動作開始メソッドです。
@scheduleUpdate()
を呼ぶことで、60FPS(すなわち16.6ms毎)でupdate
が実行されるようになります。
17~32行目は60FPS(すなわち16.6ms毎)で実行されるupdate
メソッドです。
18~22行目で移動処理を行っています。
18行目で現在時間の取得を行っています。
19~20行目で現在時間が設定時間以上だった場合設定座標で停止するようにしています。
21~22行目で現在時間と設定時間の差分よりY座標を算出し設定・移動しています。
24~32行目では現在時間が設定時間+Good判定しきい値を超えた場合にフェードアウトする処理を行っています。
25行目は外部に「BAD判定があったよー」と通知しています。
26行目で@unscheduleUpdate()
を呼び、update
を停止しています。
32行目でアニメーションを実行しています。
どんなアニメーションかを28行目で設定してます。
cc.sequence
は処理を順番に実行していきます。(ちなみに同時に実行するのは38行目のcc.spawnです。)
cc.fadeOut 0.2
で0.2秒かけてフェードアウトした後、cc.CallFunc.create cb, this
でコールバックcb
を実行します。
コールバックは27行目でcb =-> @removeFromParent on
とありますので、親要素から自身を削除します。
すなわち、「0.2秒でフェードアウトした後、親要素から自身を削除する」という処理を24~32行目で行っています。
34~47行目でタッチ時の処理を行っています。
36行目で判定処理をおこなっています。
以降は24~32行目と基本的に同じですが、cc.spawn
を使用し、cc.fadeOut 0.2
とcc.scaleBy 0.2, 1.5, 1.5
が同時に実行されるようにしています。これにより、0.2秒かけてフェードアウトしながら、1.5倍に拡大するアニメーションが実行されます。
49~59行目は判定処理です。
現在時間を取得し、設定時間との差分を計算。
パラメータで受け取った判定しきい値との比較を行い、判定結果を_trigger
メソッドでリスナーに通知しています。
61~64行目はイベント通知処理です。
@_listeners
に格納されたコールバックを実施します。
『ノート』クラスを使ってみます。
app.coffee
で『ノート』を作成し、動かしてみます。
1~3行目で各クラスをrequire
します。
10~16行目で各種『ノート』のパラメータを設定します。
今回は再生時間が4秒の時に目標座標0pxに500px/secで到達するように設定しています。
今更ですがcocos2dの場合、アプリの左下が座標(0,0)になります。
今回の場合、右下が(320,0)、右上が(320, 480)となります。
また±0.2secでGREAT判定、±0.4secでGOOD判定、それ以外はBADとなるよう設定しています。
18行~23行目で『ノート』を作成しレイヤーに追加しています。
24行目で判定が行われたときに呼び出されるリスナーを登録します。
今回は判定が行われると、_onJudge()
が呼ばれるよう登録しておきます。
25行目で『ノート』の動作を開始します。
26行目でタイマーを開始します。
28~29行目は上述した、判定時に呼ばれるメソッドで今回は判定結果をコンソールに表示します。
動かしてみます。
cocos run -p web
こんな感じになります。
判定結果がコンソールに表示されます。
ここまでのソース
手順5. 高解像度端末に対応する
main.coffeeの変更
現状のままだと高解像度端末で起動した場合、画像がぼやけてしまうらしいです。
対策として、画像は解像度が倍(以上)のものを用意する必要があります。
ただ、そのまま解像度が倍のものを使用すると倍のサイズで表示されてしまいます。
よって、表示サイズを1/2に縮小する必要がありますが、これを自動でやってくれるのがcc.director.setContentScaleFactor 2
です。
cc.director.setContentScaleFactor 2
により、画像などの表示サイズを1/2にしてくれます。
11行目に追加しています。
動かしてみると落ちてくる『ノート』が1/2になっていることが確認できると思います。
cocos run -p web
手順6. 『ノート』の『ターゲット』を描画する
app.coffeeの変更
『ノート』の『ターゲット』を描画します。
6~9行目で各種パラメータを設定しておきます。
- _keyNum : 5 #『ターゲット』をx方向に5つ描画する
- _margin : 60 #『ターゲット』のx方向マージン60px
- _offset : 38 #『ターゲット』のx方向オフセット38px
- _destY : 60 #『ターゲット』のy座標60px
43~50行目が描画メソッドです。 13行目で呼ばれています。
・app.coffee
動かしてみると『ターゲット』が描画されているのが確認できると思います。
cocos run -p web
こんな感じ。
手順7. 『ノート』を『ターゲット』に向けて落下させる
music.coffeeの追加
まずは再生する音楽に関する情報を記述したmusic.coffee
を用意します。
2~5行目にはファイルパスやカバーイメージ、再生終了時間などを記載しておきます。後で使用します。
6行目以降は何秒にどの『ターゲット』へ到達させるかを記載しています。
key
が0の場合は一番左に、key
が4の場合は一番右に落ちてきます。
app.coffeeの変更
music.coffee
で設定した内容に沿って動作するよう修正します。
11行~14行目で落下速度や判定しきい値を設定しています。
35行~46行目で落下してくる予定の『ノート』を作りおきしておきます。
ゲーム中にスプライトを作成するとメモリを確保のためにGC(ガベージコレクション)が実行される可能性があるためです。
GCが走っている間、プログラムが停止するため、アニメーションがカクカクになったりします。
このためメモリはゲーム中に確保したり破棄するのではなく、初期化時に極力確保しておきGCの回数を最小限にする必要があるそうです。
このあたりが参考になります。
ここでは一旦画面外に描画しておき、配列にpushしておきます。
手順4でも記述しましたが、update
はscheduleUpdate()
が呼ばれることでおよそ60FPSで実行されるメソッドです。
update
メソッド内では『ノート』の落下に要する時間や現在時間、到達時間などから動作を開始すべき時間を計算し、必要に応じて動作の開始を行います。
・app.coffee
動かしてみると『ターゲット』に向かって『ノート』が落下していくの確認できると思います。
cocos run -p web
こんな感じ。
手順8. ゲーム終了判定と終了画面を実装する
gameOver.coffeeの追加
終了時に表示するゲームオーバーシーンの追加を行います。 中央に”Game Over”と表示するのみのシーンです。
・gameOver.coffee
app.coffeeの変更
5行目でgameOver.coffee
をrequireします。
36行~39行目にゲーム終了処理を追記しています。
update
内で現在時間がmusic.coffee
に設定したplayTime
を超えていないかモニタし超えていたら終了処理を行います。
37行目でゲームオーバーシーンを作成しています。
38行目でupdate
を停止しています。
39行目でゲームオーバーシーンにシーンを切替えています。
cc.director.runScene
にnew cc.TransitionFade(1.2, gameOver)
を渡すことで1.2秒でフェードしながらシーンを切替えることができます。
・app.coffee
動かすとシーン切替後"Game Over"と表示され、シーンが切り替わっていることを確認できると思います。
cocos run -p web
手順9. スタートメッセージの追加と楽曲の再生を実装する
app.coffeeの変更
スタートメッセージをタッチすることでゲームが開始するようにします。
主な追加箇所は79~110行目です。
_addStartButton
ではスタートメッセージの追加を行っています。
基本的には画面中央にメッセージを表示するだけなんですが、cc.sequence
とcc.RepeatForever
を使用することで1秒間隔で永久に点滅するようにしています。
また90~94行目でタッチイベントを登録しています。メッセージがタッチされると、96行目の_onTouchStart
が実行されます。
_onTouchStart
はごちゃごちゃしていますが、ほぼタッチのための処理であり、基本的には102行目の”自身を親から削除する”と103行目の”楽曲を再生する”がメインの処理です。
107~110行目の_timerStartIfMusicPlaying
ではBGMが再生中か判断し、再生中であればタイマーを開始しています。
_onTouchStart
内で再生していますが、@_music.playMusic
から実際に再生が始まるまでタイムラグがあるようなので(環境によるものかもしれませんが)このようにしています。この方法でも多少のずれは発生しますが、無視できるレベルだと思います。
スケジュールは27行目でセットしており、タイマ開始とともにうスケジュールをクリアしています。
・app.coffee これで一応最低限遊ぶことができるようになりました。
手順10. スコアの計算と表示を行う
app.coffeeの変更
スコアの計算と表示を行います。
118~125行目でスコアラベルの追加を行っています。
_onJudge()
で判定結果に合わせてスコアの計算を行っています。
すべてGreat判定の場合100000点、すべてgoodの場合70000点となるように計算しています。
・app.coffee
手順11. 判定結果の表示を行う
app.coffeeの変更
判定結果の表示を行います。
133~141行目で判定表示ラベルの追加を行っています。
_onJudge()
で判定結果に合わせて判定表示ラベルの文字列を変更しています。
変更後、_showJudgeLabel()
により一定期間判定表示ラベルを表示します。
具体的には
seq = cc.sequence cc.fadeIn(0.2), cc.fadeOut(1) @_judgeLabel.runAction seq
で0.2秒かけてフェードイン、1秒かけてフェードアウトさせています。
・app.coffee
手順12. 楽曲カバーイメージとタイトルの表示を行う
app.coffeeの変更
もはや説明不要かと思いますが、カバーイメージとタイトルの表示を行います。
149行~163行目の_addCoverImage()
、_addTitle()
で表示を行っています。
・app.coffee
以上です。一応音ゲーっぽくはなったと思います。 お疲れ様でした。
リポジトリは以下です。 色々いじって遊んでみてください。
さいごに
実はなんですが、もともとAndroid/iOS両対応のアプリを作る記事として書き始めたんですが現状の書き方だと、ネイティブ動作でうまくいかないこが分かり、WEBアプリの記事にピボットしました。ネイティブ用に修正する気力がもてなかったため、公開もやめようと思いましたが、途中まで書いていたこともあり、中途半端ながら公開することとします。
おそらくですが、『ノート』のタッチイベントの登録のところで上手くいっていないと思います。sampleのTouchesTest
も何故かネイティブ動作NGになっていますので多分問題があるのだと思います。
気になる方はcocos2d-js-v3.x/samples/js-tests
でcocos run -p web
とかcocos run -p ios
し、ソースと比較しながらいろいろ試してみてください。
またAndroid版とそのソースも公開しているので参考にしてみてください。
![cocos2d-xではじめるスマートフォンゲーム開発 [cocos2d-x Ver.3対応] for iOS/Android cocos2d-xではじめるスマートフォンゲーム開発 [cocos2d-x Ver.3対応] for iOS/Android](http://ecx.images-amazon.com/images/I/61B28TFhuKL._SL160_.jpg)
cocos2d-xではじめるスマートフォンゲーム開発 [cocos2d-x Ver.3対応] for iOS/Android
- 作者: 三木康暉
- 出版社/メーカー: 技術評論社
- 発売日: 2014/12/27
- メディア: 大型本
- この商品を含むブログを見る