CSSだけでTemple Runをつくる
どうも。 おっぱいの人 です。未だホンモノにはありつけていません。
このエントリは、CSS Programming Advent Calendar 2012 23日目の記事です。
CSS Programmingとは
もう今更説明しようがないですよね。
おっぱいとかそんなんより数倍変態な人たちがHTMLとCSSだけでゲームとか作っちゃうアレです。
ぼくはというと、今年一年中ガラケーと戦ってた(業務的に)のでCSS3とか実はほとんど触れていないので、リハビリの意味を込めての復帰戦となります。
CSSだけでTemple Runをつくる
Temple Runってコレです。iPhoneのランニングゲー(?)では一番有名ですよね。
手前味噌で恐縮ですが、Tap Ninja なんというのもKAYACさんからでております。ああ、すみません宣伝では無いんです。石を投げないでください。ごめんなさいごめんなさい。
というのも、今回はちょっと実装量的にもTap Ninjaに近くしたので紹介しました。
さて残された時間も少ないので早速のお披露目です!
CSS Temple Run
動作コードはjsdo.itに貼り付けました。
Chromeでのみ動作を確認しています。
相変わらず、少し大きく作り過ぎちゃったので(jsrun.it)http://jsrun.it/damele0n/jofZのほうで画面を広げて見てください。
キャラクターあたりをクリックして迫り来るサンタクロースの恐怖を回避しよう!!!!
…すごい…!これは、すごい!なんだろう、このすごいコレジャナイ感!!!!!!
Temple Runのいいところを120%握りつぶすようなシュール感と、絶対にやっちゃいけないゲームの琴線に触れたつまらなさが本作品のウリです。
大反省会
難しいですね。CSS Programming。いや、舐めてたわけじゃ無いんですよ?いやホントに。ああ、石を投げないでください。犬を放たないでください。ああ。
今回、sassのsassたる形式を使ったのでjsdo.it上でコンパイルできなくなってしまい、仕方なくjsdo.it上にはコンパイル後のファイルをベタで置いてあります。
動作品の完全なコードは、githubに上げておきました。
画面上の仕組みとしては、
- 背景
- 人物やサンタ、隠れたradioなど
で構成してあります。
背景レイヤーについては大まかに
// 背景のコンテナ .bg { // 遠近感を設定 -webkit-perspective: 500; } // .road, .wall_l, .wall_rの3面で壁を構成 .road { top: 35px; width: 300px; height: 500px; -webkit-transform: rotateX(-290deg); } .wall_l { top: 23px; left: -360px; width: 770px; height: 200px; -webkit-transform: rotateY(98.6deg); } .wall_r { top: 23px; left: -110px; width: 770px; height: 200px; -webkit-transform: rotateY(-98.6deg); }
として、座標系とrotateをいじりながら3面を3Dで配置しました。DevTool見ながら手で。(強引)
逆に操作系というか、パーツ系というか、アニメーションなどが絡むものは全て2Dで扱っています。
// input[type=radio]へ適用。radio自体は隠しちゃう。 .state { -webkit-appearance: none; &[value=left]:checked { // checkedとは逆の要素にむけたlabelのz-indexを上げる & ~ .ctrl_r { z-index: 10; } // background-positionで裸のオッサンの位置を変える & ~ .action { background-position: left top; } } &[value=right]:checked { & ~ .ctrl_l { z-index: 10; } & ~ .action { background-position: right top; } } } // 衝突やオッサンの方向などは.actionがすべてもつようにする .action { position: absolute; z-index: 9; top: 410px; left: -50px; width: 400px; height: 150px; background-image: url(https://dl.dropbox.com/s/ef9pdfctl2fr12n/charactor.gif); background-repeat: no-repeat; background-position: left top; opacity: 1; } // 凶悪なサンタクロースたちのスタイル // アニメで動かすので、とりあえず適当に配置してopacity:0に .stage a[class*=block_] { position: absolute; z-index: 11; top: 105px; left: 55px; width: 190px; height: 70px; -webkit-appearance: none; background-image: url(https://dl.dropbox.com/s/63z2uiqq1060bbu/santa.png); background-repeat: no-repeat; background-size: auto 100%; opacity: 0; } // 衝突情報とdelay秒数のブレのセット // 0 なら left, 1 なら right で衝突 $blocks: 0 0, 1 0, 0 -1, ...; // ディレイのベース秒数 $delay_base: 2.5; // 衝突情報を元にスタイルを書き出す @for $i from 1 through length($blocks) { $block: nth($blocks, $i); $angle: nth($block, 1); $delay: ($delay_base * $i) + nth($block, 2); $class_name: block_#{$i}; // 左で衝突の場合、#state_lのcheckboxがcheckedであったらcrashのアニメを.action上で再生 @if $angle == 0 { #state_l:checked ~ .#{$class_name}:hover ~ .action { @extend %crash; } } // 右で衝突の場合、#state_rのcheckboxがcheckedであったらcrashのアニメを.action上で再生 @else { #state_r:checked ~ .#{$class_name}:hover ~ .action { @extend %crash; } } // $iの番号を元に.base_Nの要素に対して、ディレイと方向を設定する .#{$class_name} { -webkit-animation-delay: #{$delay}s; @if $angle == 0 { background-position: left top; } @else { background-position: right top; } } }
このあたりは、たぶんCSS Programmerなら誰でもやってる(?) "~"セレクタ連結で状態を管理しながら画面表示を行う手法です。
また、SCSS内各所にてcreate-animeというmixinを呼んでいますが、実は3ヶ月ほど温めておいたものです。
その名の通り、animationを簡単に作れるようにしたものなんですが、ポイントとして設定されたFPSでアニメーションを書き出せるという点です。
// 従来のkeyframes // 秒数あたりのパーセントで動いてちょっとキモイ。っていうか分かりづらい。(個人的な感想です) @keyframes hogehoge { 0% { //prop: value; } ... 100% { //prop: value; } } // create-animeだと @include create-anime( // アニメーション名を設定。placeholder形式ではき出す(%hogehoge)ので使用するセレクタ内で@extend %hogehogeする 'hogehoge', // その他animationの設定値を設定 ( timing-function linear, iteration-count infinite ), // ここでいう1はFPSあたりの1フレームのこと。FPS: 24ならフレーム内秒(1/24)*1 1, ( background-position (center top) ), // 100フレームの意。FPS: 24ならフレーム内秒(1/24)*100 // animation-durationは最後の設定フレームから自動的に設定される 100, ( background-position (center bottom) ) ); // 書き出されるとこんな感じ .hogehoge { animation-name: kf-hogehoge; animation-duration: 4.16667s; animation-timing-function: linear; animation-iteration-count: infinite; } @keyframes kf-hogehoge { 1% { background-position: center top; } 100% { background-position: center bottom; } }
ね、フレーム単位でカウントした方が分かりやすいし、他のアニメーションとも連携しやすそうじゃないですか?
突貫で作ったのでまだまだ機能不足ですが、create-animeはこれだけ別にしてまたの機会に。
おわり
今23:54です。何とか間に合いました。
クリスマスの予定など皆無かつ、当然のように明日も仕事ですが、みなさんは素敵なクリスマスをお過ごしくださいね。
ぼくは駅前で踏み絵でもしようと思います。
さて、明日は No_1026 さんの「ギャンブる」なお話です。お楽しみに!