COLOPL Engineers' Blog

COLOPL Engineers' Blog

コロプラのエンジニアが開発ノウハウや技術トピックスなどを発信しています

2012.10.19

CSSアニメーションでスロット風くじを実装:後編

ここのところ急に寒くなって来ましたが、ごきげんいかがでしょうか。
エンジニアの mattari_panda です。

さて今回は「CSSアニメーションでスロット風くじを実装:前編」の続きです。
前回残していた課題は以下のとおりです。

  • 見た目の問題(モックなので当然なのですが)
  • STOPを連打すると変わってしまう
  • 止めた時の唐突感
  • すべりをどう表現するか

今回はこれらを解消して行きましょう。

止めた時の唐突感

突然目的のコマで止めてしまうと、唐突感が出てしまい表現としても チープなものになってしまいます。

実際のスロットのように少し手前で止まり始め、目的のコマに近づくにつれて 速度を落とし止まるようにするために、CSSの「Transition」で加速度をつけます。


(抜粋したコード

.stop{
      -webkit-transition:-webkit-transform 1s ease-out;
}


このように記述することで「transform」の値を1秒かけて「ease-out(減速)」する アニメーションになります。

またゆっくりと止めることが出来るようにちょっとしたトリックを使っています。

前回まではコマの数だけ「li」タグがあったのですが、コマが個数分しかないと上の方のコマを止めるときはどうしてもゆっくり止まってくれません。

そこでもうひとセット(5×2で全部で10こ)コマを用意することで、動かせる幅が広がり ゆっくりと止めることができます。コレを実装したこのがこちらです。

これで自然なストップアニメーションができました。

見た目の問題:CSSのグラデーションで対応

見た目の問題」はスロットでドラムの奥行きを表現するために
簡単ですが、背景色にCSSのグラデーションを敷くことにします。


(抜粋したコード

#srotWindow{
    /*webkitのみ対応*/
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(1, #a8a8a8), color-stop(0.7, #fdfdfd), color-stop(0.3, white), color-stop(0, #a8a8a8));
    background-image: -webkit-linear-gradient(top, #a8a8a8 0%, white 30%, #fdfdfd 70%, #a8a8a8 100%);
    background-image: linear-gradient(to bottom, #a8a8a8 0%, white 30%, #fdfdfd 70%, #a8a8a8 100%);
}


このようなグラデーションの指定で、簡素ながらドラムっぽくしました。
もっときちんと「奥から出てくる」感じを出すこともできるのですが、
他の課題に重点を置きたいので、今回はやめておきます。(そのうちやるかもしれません)

STOPを連打すると変わってしまう

こちらはすでに止まっていてもSTOPを押すたびにクラスが変化していることが原因です。 ですので、JavaScriptでスロットが止まっているときはSTOPを押しても何もしないようにします。


(抜粋したコード

    //スロットが回っている最中かどうかを判定するフラグ
    var slotFlag = false;

    var btnStart$ = document.querySelector('.start'); 
    var btnStop$  = document.querySelector('.stop');

    btnStart$.addEventListener(eventPress, function(ev){
        if(!slotFlag){
            slotFlag = true;
            //ここでスタートした時の処理
        }
    });

    btnStop$.addEventListener(eventPress, function(ev){
        if(slotFlag){
            slotFlag = false;
            //ここでストップした時の処理
        }
    });


「slotFlag」という変数をフラグにして、STARTとSTOPを押した時に切り替えることで、 「スロットが回っているかどうか」の状態を記憶させます。

この変数を参照することで、「回っているのに回そうとする」や「止まっているのに止めようとする」ことを防いでいます。

すべりをどう表現するか

今回は「すべり(当たったと思ったら次のコマで止まった)」ではなく、「もどり(外れたと思ったら戻ってきた)」を実装しました。「すべり」は前述の「ゆっくり止まる」ことで少し期待感を出せていると思ったからです。

「もどり」を実装するには「行き過ぎる(回り過ぎる)」表現をするわけですが、前回のVol.3のようにCSSのTransitionで表現するとtopの値をJavaScriptで細かく変更しなくてはなりません。

JavaScriptに短時間に多くの処理をさせると、負荷の原因になりますのでここではCSSのanimationをつかいます。


(抜粋したコード

#srotWindow > ul.num1 {
  -webkit-animation: slotAnime1 1s ease-out;
  top: 0px;/*目的の値:アニメーションの巻き戻り防止*/
}

@-webkit-keyframes slotAnime1 {
  0% {
    top: -160px;/*初期値*/
  }
  80% {/*←ココがポイント*/
    top: 20px;/*目的より行き過ぎた値*/
  }
  100% {
    top: 0px;/*目的の値*/
  }
}


このようにanimationを設定することで、「80%」のパーセントの値を調整することで、 戻りの速度も調整できます。

また「#srotWindow > ul.num1」内でアニメーションだけでなく「top: 0px;」も指定してあるのは Android古いバージョンなどでアニメーションが最初の値に戻ってしまうことがあるので、それを防止するために記述しています。

完成

全てを実装したコードがこちらです。

ボタンは簡単に実装しているので、特に取り上げませんがこれで「スロット」としての機能と簡単な見た目は出来上がりです。ここから更にカスタマイズしてアプリなどに載せています。

いかがでしょうか。今回のポイントは

  • CSSでできることは極力CSSで
  • JavaScriptはイベント(ボタンを押すなど)と結果を出す操作だけ

このふたつに注力しできるだけ軽快に動くようにしたことです。 次回も実践的なテクニックを紹介したいと思いますので、ぜひお読みください。

2012.09.14

第四回 Ebisu.tech を開催しました

こんにちは。エンジニアのliguriaです。

2012年8月29日に、クックパッドさんのオフィスをお借りして 第四回Ebisu.tech と称したエンジニア交流会を開催させていただきました。 Ebisu.tech は恵比寿周辺で働くエンジニアさんと交流して刺激を受けよう!ということで始まり、今回で第四回をむかえることができました。

今回のテーマは会社毎の環境や雰囲気などを織り交ぜた発表中心で、弊社からは プロ野球PRIDE(iPhone, Android) をリリースする前の開発秘話をしました。

発表資料は以下に公開させていただきますので、よろしければ御覧ください。

発表を終えた後はお待ちかねのメインイベント専属シェフさんの料理が登場。

交流しながら食べやすいようにと、フィンガーフード形式で用意していただきました!

どれも美味しくいただきましたが、サムギョプサル巻は思い出しただけでも幸せになれます。

弊社コロカ提携店の商品もご好評いただきました。

様々な環境で働くエンジニアさんと交流できる場があるのはとても幸せで、集まっていただき本当に感謝しております。

今後も続けて、いい刺激を与えあって行きたいです。

2012.08.24

CSSアニメーションでスロット風くじを実装:前編

こんにちは。エンジニアの mattari_panda です。
みなさま残暑いかがお過ごしでしょうか。

さて今回は先日弊社アプリにおいてCSSアニメーションで実装した、
「スロット風くじ」をご紹介したいと思います。

前回のアニメーションの記事同様、今回も要件定義から実際に実務で使えるレベルになるまでの過程も書いていきます。

要件定義

今回の要件は以下のとおりです。

  • スロットのドラムはひとつ(絵合わせではない)
  • 目の数は後でも変えられるように
  • できれば「すべり」も実現したい

イメージはこんな感じです

  • いつつめ
  • よっつめ
  • みっつめ
  • ふたつめ
  • ひとつめ

HTMLの構成はシンプルです。
親のdivがスロットの目が見える窓になり、子要素のul全体がドラムになります。
そしてliタグそれそれが揃っとの目になります。
divに「overflow:hidden;」のCSSスタイルを適応すればできそうです。

簡単なモックを作る

まずはHTMLとCSSだけの簡単なモックアップを作ります。
この状態でブラウザのDeveloper ToolsなどでCSSの値を変更し
どのようにアニメーションさせれば良いかを決めます。

この場合はひとまずulタグを「position:absolute;」で絶対配置にしているので
CSSの「top」の値をアニメーションさせればよさそうです。
コレをキーフレームアニメーションで表現するとこのように出来ます。

@-webkit-keyframes slotAnime {
    0% {top:-500%}
    100% {top:0%;}
}


これを繰り返すように指定すれば、ドラムが回っているような表現になります。
更に次のモックでは「START」と「STOP」のボタンとそれを押し
ドラムを回転させ止まるところまで実装します。
ulタグにクラス「play」が充たると、先ほどのアニメーションが始まるように
CSS側で設定します。

.play{
    -webkit-animation: 'slotAnime' 0.5s linear infinite;
    animation: 'slotAnime' 0.5s linear infinite;
}


「START」を押すとこの「play」クラスが充たるようにするには
CSSのみでできないこともありませんが、今回はその後のスロットの
当たり目の結果をランダムに決めるので、クラスを充てるのもJavaScriptで
おこないます。
さきほどのCSSでtopの位置をアニメーションさせているので、
「STOP」を押すとランダムで1〜5までの当たり目が決まります。

親のdivの高さと各リストの高さを40pxで揃えているので、
当たりの数値に対してulタグのtopの位置を決めるには、
あたり1の時:top:-160px
あたり2の時:top:-120px
あたり3の時:top:-80px
あたり4の時:top:-40px
あたり5の時:top:0px
で止まればよいので、

var stopNum = Math.ceil( Math.random() * -5 )* 40;


という計算式で求めることができます。
できたモックがこちらです。


ひとまずモックはできましたが、この状態ではまだいくつか課題があります。

  • 見た目の問題(モックなので当然なのですが)
  • 止めた時の唐突感
  • STOPを連打すると変わってしまう
  • すべりをどう表現するか

くじとしての機能は果たしていますが、ココからはいかにうまく表現するかを追求することになります。
次回、後編ではその部分を詳しく書いてみます。

2012.08.07

コマンドラインとブラウザで JSON API を手軽に試す

こんにちは。エンジニアの hatak です。

ウェブサービスにおいて API を開発するケースでは、サーバからのレスポンスが HTML ではなく JSON などのデータフォーマットになることがあります。 この API が RESTful な設計である場合、ブラウザでは扱いにくい PUT / DELETE などのメソッドを使うケースもあります。

このような API を試すときに手軽にできる方法を、コマンドラインとブラウザでそれぞれまとめてみました。

今回はダミーの JSON を返す簡易的なサーバを用意しています。 レスポンスに対して、下記のキーを JSON 形式で応答するだけのシンプルなサーバです。

  • query_strings : GET で送信されるクエリストリング
  • body_parameters : POST/PUT で送信されるボディパラメータ
  • method : リクエストの HTTP メソッド
  • message : ダミー文字列

ローカルのポート 5000 番で立ち上げたサーバに対してリクエストを送りながら試してみます。

コマンドラインで試す - curl

コマンドラインで手軽に試す方法としては、curl コマンドがあります。

$ curl -s -i "http://localhost:5000"
HTTP/1.0 200 OK
Date: Tue, 07 Aug 2012 08:42:00 GMT
Server: HTTP::Server::PSGI
Content-Type: application/json
Content-Length: 86

{"query_strings":{},"body_parameters":{},"method":"GET","message":"Hello JSON World!"}

"-i" オプションでレスポンスヘッダの表示が行えます。 GET や POST のリクエストを試してみると、ちゃんとレスポンスに反映されていることがわかります。

$ curl -s -i -X GET "http://localhost:5000/?a=hoge&b=fuga"
HTTP/1.0 200 OK
Date: Tue, 07 Aug 2012 08:43:45 GMT
Server: HTTP::Server::PSGI
Content-Type: application/json
Content-Length: 107
{"query_strings":{"a":"hoge","b":"fuga"},"body_parameters":{},"method":"GET","message":"Hello JSON World!"}
$ curl -s -i -X POST  -d 'a=hoge' -d 'b=fuga' "http://localhost:5000/"
HTTP/1.0 200 OK
Date: Tue, 07 Aug 2012 08:44:35 GMT
Server: HTTP::Server::PSGI
Content-Type: application/json
Content-Length: 108

{"query_strings":{},"body_parameters":{"a":"hoge","b":"fuga"},"method":"POST","message":"Hello JSON World!"}
$ curl -s -i -X PUT  -d 'a=hoge' -d 'b=fuga' "http://localhost:5000/"
HTTP/1.0 200 OK
Date: Tue, 07 Aug 2012 08:44:41 GMT
Server: HTTP::Server::PSGI
Content-Type: application/json
Content-Length: 107

{"query_strings":{},"body_parameters":{"a":"hoge","b":"fuga"},"method":"PUT","message":"Hello JSON World!"}

しかし、よく見るとレスポンスの JSON が読みにくい状態のままなので、JSON を読みたいときは Perl のワンライナーを通すことで整形します。

$ curl -s -X GET "http://localhost:5000/?a=hoge&b=fuga" | perl -MJSON -E "say to_json(decode_json(<>), { pretty => 1 });"
{
   "query_strings" : {
      "a" : "hoge",
      "b" : "fuga"
   },
   "body_parameters" : {},
   "method" : "GET",
   "message" : "Hello JSON World!"
}

curl コマンドは cookie をファイルとして保存し、リクエスト時に付加することもできます。また、任意のリクエストヘッダを付与することもできます。これらのオプションを組み合わせれば、認証がかかっているような API でも気軽に試すことができます。

ブラウザで試す - Firefox RESTClient

コマンドラインよりももっと簡単に試したい、というときに便利なのがブラウザです。しかし、通常のブラウザでは PUT / DELETE などのメソッドは使えません。 そこで、Firefox の RESTClient というアドオンを利用します。

インストールすると、[ツール] メニューに [RESTClient] という項目が追加されます。 あとは Method を選択、URL を入力したあとに "SEND" をクリックするとレスポンスが表示されます。

タブを切り替えると JSON を綺麗に整形して表示してくれるので手軽ですね。

POST / PUT でボディパラメータを送りたい場合は、 Body に入力をした上で Headers に "Content-Type: application/x-www-form-urlencoded" をつける必要があります。[Headers] - [CustomHeader] から追加できます。

Web には多くの JSON API が提供されてるサービスがあります。実際に API のレスポンスを見て、新しいサービスのヒントにできるとよいですね。

2012.07.27

jsdo.it内SPEC vol.4の結果発表

こんにちは。エンジニアの mattari_panda です。

6月27日から開催していたSPEC vol.4の結果を昨日発表しました。

詳しくはこちらから御覧ください。 SPEC vol.4

さて今回のブログではどのようなところに着目して、審査を行ったかをお話します。

金賞の作品はこちら

演出面はシーンに合ったもの

今回の審査を「演出面」と「コードの質」の2つを軸に評価させていただいたことは SPECの総評に書いたとおりです。

まずは「演出面」ですが、こちらは人によって評価が別れる可能性があったので 社内での投票という形を取りました。

しかし蓋を開けてみると、受賞した作品に票が集中しました。なぜでしょうか? 実はこれにはお題にヒントがあったのです。

お題には 「サンプルは「プロ野球PRIDE」で実際に使われている「代表試合」(ゲームのBOSS戦にあたります)の開始時の演出画面です、これをHTML5+CSS3+JavaScriptを駆使して自由にアレンジしてもらいます。」 とあります。

あくまで『「プロ野球PRIDE」で実際に使われている「代表試合」』をアレンジするのがお題になるので、そのシーンに合うものとして評価されたわけです。 お題のサンプルがなぜ短いのかを考えると、ユーザーに「代表試合」が始まる前の演出として考えると「過度に長過ぎるもの」は必ずしも良いとは言えません。どんなに素晴らしい演出でもそのシーンに合うかどうかは、技術的な部分より時として重要であるというわけです。

金賞と銀賞を受賞された作品はどちらも10秒前後ですが、テンポもよく最後のシーンまでのつなぎ方も素晴らしいものでした。

コード面は柔軟性と発想力

「コードの質」の部分に関しては「柔軟性」と「発想力」を評価の基準にしました。 今回のお題の大きな特徴である「CanvasとSVG禁止」というのがありますが、これを聞くと「CSS3しかない!」と思ってしまいがちです。 しかし「JavaScript」自体を禁止しているわけでないので、CSSのみに拘る必要はありません。

もちろん「CSS3だけで表現できる限界に挑戦しよう!」という気概はコードを書くものとしてとてもよくわかるのですが、それならば独自の「発想力」でCSSとは思えない表現を見てみたいという気持ちになります。

金賞を受賞された作品は、CSSのみにこだわることなく思いついた表現を実現するべく「柔軟性」のあるコードになっています。銀賞を受賞された作品は、独自の「発想力」が光り他の作品とは一線を画するものでした。

「コードの質」というのはもちろん仕様を理解したものであったり、綺麗なものであったりする部分もあるのですが、その結果できたコードがどこにでもあったり、誰にでも思いつくものであったりすると、結果的にユーザーに見せる部分はどこかで見たことがあるような面白みのないものになってしまいます。

まとめは「SPEC」のコンセプトにあり

これらのことを重視したのはSPECという企画が単なる「アイデアコンテスト」ではなく、あくまで「クリエイターの採用試験」を兼ねたものであるからです。

共にコロプラで働きたいと思う人物には、ゲームやシーンにあった演出を考える力と実現する(形にする)ことを重視する柔軟性を持っていただきたいという思いから、今回の審査に至りました。

最近はいろいろなコンテストがありますが、企画の趣旨やコンテストのお題というものはブレてはいけないものであるのではないかと思います。今回惜しくも受賞を逃した方々も他のコンテストなどに応募される際は参考にしていただけるとなによりです。