これなに?
ブラウザ上で遊べる音ゲーです。 ノートと呼ばれるオブジェクトが曲に合わせて落ちてくるのでターゲットに重なるタイミングでキーボードのZ,X,C,V,Bを押していくゲームです。 楽曲はCreativeCommonsのものを使用しています。
なんで作ったの?
Vue.jsやReactやAngularJSやAurelia.JSなどフレームワークが乱立するなか何か一つ使えるようにならないといけない気がしたので勉強用に始めました。(あとcocos2d-JSのAndroidデバッグが嫌になりましたので気分転換に)。最初はAngularJSより学習コストの低そうなVue.jsを触ろうかと思ったのでですが、Vue.jsにはルーティング機能がついていないということで結局AngularJSを触ってみることにしました。(書籍も買っちゃってたし。)
本来ゲームであればenchant.jsでシーンの切替え等を行い、AngularJSなどを使わないってのが普通な気がしますが、今回のような曲選択ページなんかはゲーム側でjavascriptで記述するよりhtmlとして表示してやったほうが簡単だとおもったので・・。実際cocos2d-JSで同じようなメニューページをjavascriptで書くのは少し面倒に感じました。
後はおもけに以下のことを試したみました。
- webstorage使ってみる(ハイスコアの記録に使っています)
- GitHubPages上で公開してみる(無料だし独自ドメイン使えるし)
リポジトリ
はまったこととか、こんな風にやってみましたってこととか
AngularJSは情報が多いとはいえ、やはり手さぐりでいろいろ調べながら試しました。『こうすべきだ!』ってのがあったらご教示いただけると幸いです。
GitHub Pagesで独自ドメインを使用する
以下のページが非常に参考になりました。というかまんまです。
GitHub Pages でWebサイトをホスティングする(独自ドメイン使用) - Think Big Act Local
AngularJSでルーティングする
以下のページが参考になりました。
inter-arteq :: interaction between art and technology » Blog Archive » AngularJSで画面遷移するときに便利なng-view
index.htmlに以下のように記述しておき
<div ng-view id="view"></div>
JS側で以下のように振り分けています。
flavaApp.config ($routeProvider)-> $routeProvider .when '/', templateUrl: 'splash.html' .when '/select', templateUrl: 'select.html' .when '/help', templateUrl: 'help.html' .when '/game/:id', controller: 'GameCtrl' templateUrl: 'game.html' .otherwise redirectTo: '/'
また、URLのパラメータを取得するのには以下のページを参考にさせていただきました。
$routeParamsを使用して、URLのパラメータを取得する | 集の一期一会
具体的には
flavaApp = angular.module('flavaApp', ['ngRoute']) flavaApp.config ($routeProvider)-> $routeProvider .when '/game/:id', controller: 'GameCtrl' templateUrl: 'game.html' flavaApp.controller 'GameCtrl', ($scope, $routeParams)-> console.log $routeParams.id
とするこでhttp://prototype.flavabeats.net/#/game/1にアクセスすることで$routeParams.id
が1
になります。これを使って、ゲームプレイ時はすべてgame.htmlに遷移しつつ、idによってどの楽曲をプレイするか選択しました。
外部ライブラリのコールバックの中等で $scope の値を変更したい場合
以下の記事が参考になりました。
AngularJSでデータバインドが効かないときは $scope.$apply - Yuta Watanabe's Blog
リンク先の記事でも紹介されている、2秒後に$scope.message
を書き換える例ですが以下の記述では動作せず。
function Ctrl($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.message = "Timeout called!"; // AngularJS unaware of update to $scope }, 2000); }
以下のように各必要があるようです。
function Ctrl($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.$apply(function () { $scope.message = "Timeout called!"; }); }, 2000); }
HTMLとして文字列をバインドする
以下の記事が参考になりました。
3分で分かるAngularJSセキュリティ - teppeis blog
今回はangular-sanitize.js
を使用しました。
以下のようにレベルをhtmlで表示しています。
html
<span class="level" ng-bind-html="m.levelIcon"></span>
JS側
flavaApp = angular.module('flavaApp', ['ngSanitize']) flavaApp.controller 'GameInfoCtrl', ($scope)-> level = 'Level ' for i in [0..9] when i < $scope.music.level level += '<i class="fa fa-star-o level"></i>' $scope.music.levelIcon = level
topページでスマホ用にメッセージを出す
性懲りもなくスマホには対応していないので、スマホユーザには非対応メッセージを出すようにしました。
userAgent
を判定して、ng-hide
とng-show
で要素を表示・非表示にして対応してます。
html
<div class="row" ng-controller="SplashCtrl"> <div class="col-md-8 col-md-offset-2 text-center inner" ng-hide="isMobile"> <a ng-href="#/select"><h1><img src="img/logo.png" ></h1> <span class="click-message">Click here to start.</span></a> </div> <div class="col-md-8 col-md-offset-2 text-center inner" ng-show="isMobile"> <h1><img src="img/logo.png" class="sp-logo"></h1> <span class="mobile-message">Sorry, This site is designed specifically for PCs.</span> </div> </div>
JS側
flavaApp.controller 'SplashCtrl', ($scope)-> agent = navigator.userAgent if agent.search(/(iPhone|iPod|Android|Mobile)/) isnt -1 then $scope.isMobile = on else $scope.isMobile = off
webstorageを使う
こんな感じで保存
storage = localStorage storage.setItem key, value
こんな感じで読み出し
storage.getItem key
できるっぽいです。簡単。
さいごに
インクリメンタルサーチとかソートとかさくっと実装できて楽しかった。もっと勉強してVue.jsやAurelia.JSも触ってみたい。あと、せっかくなんだからBrowserify使ってみればよかった。
※追記
ゲームへの使用例が以下の記事に掲載されていました。