UIT meetup vol.7 集まれ!(タブン)実務では使わないフロントエンド芸発表会
- @GeckoTang
- 坂巻 翔大郎
- 株式会社ピクセルグリッド
https://codepen.io/geckotang/pen/wLXZvr
- 2012年頃に作りました(7年前!)※
- JavaScriptを使っていない
- HTMLとCSSで作られたワニワニパニック風(?)のゲーム
- 画像も全部自分で作りました
※jsdo.itで公開したのが2011年とかそこらへん。
jsdo.itだと見れないことが多いのでCodePenに移植しました
ndrugerさんの作ったjavascriptを使わず、html + cssだけでクリックシューティングゲームを作ってみたが基本となる仕組みです。
私はそこに、ゲームのプレイ画面とゲームオーバー画面、そして見た目をつけて整えただけ。
- 状態の管理
- プレイ画面の制限時間の管理
- ワニをクリックしたとき
- もう一度遊ぶ
- 見た目の装飾
- base64 encode dataURI
apperance
プロパティ
- 動き
- CSS Animations
- プレイ画面の制限時間の管理
- ワニをクリックしたとき
- もう一度遊ぶ
- 一定時間後ゲームを終了させたい
- 残り時間を示すゲージ
<div id="game">
<a id="gameover" href="https://..."></a>
<div id="timer"><div id="progress"></div></div>
<div id="map">
/* setting : gameover */
#gameover{
position: absolute;
top:0;
left:0;
-webkit-animation-name:gameover;
-webkit-animation-timing-function:linear;
-webkit-animation-duration:13s;
-webkit-animation-delay:0.5s;
opacity:1;
}
@-webkit-keyframes gameover{
0% {top:-465px;opacity:1;}
97% {top:-465px;opacity:0;}
100% {top:0px;opacity:1;}
}
今だったらまた違った方法でやるかもしれないけど、当時はこうしてたらしい。
- なくてもいいと思うけど、あるとゲームっぽいので。
- 幅が0pxの状態から12.5sかけて200pxになる。
<div id="game">
<a id="gameover" href="https://..."></a>
<div id="timer"><div id="progress"></div></div>
<div id="map">
#timer{
position: absolute;
top:310px;
left:5px;
z-index:10;
width: 309px;
height: 50px;
}
#progress{
position: absolute;
top:7px;
left:97px;
width:200px;
height: 36px;
-webkit-animation-name:progress;
-webkit-animation-timing-function:linear;
-webkit-animation-duration:12.5s;
-webkit-animation-delay:0.5s;
}
@-webkit-keyframes progress{
0% {width:0px;}
100% {width:200px;}
}
- 吹き出しを表示する
- スコアのカウントアップ
「ワニはラジオボタンでできている」
ラジオボタンの動作をおさらい
<input type="radio" name="foo" checked> 項目A
<input type="radio" name="foo"> 項目A
input[type="radio"] { }
input[type="radio"]:checked { }
- 同じname属性値を持つラジオボタン内で1つだけcheckedにできる
- 一度checkedになったラジオボタンはもう一度押してもチェックを外れることがない
input[type="checkbox"]
でも:checked
が使える。ただチェックが外せてしまう
:checkedでなにかする
input:checked
と隣接セレクタ等を組み合わせれば、チェックされたときにいろいろな要素をいじることができる- ON/OFFできる便利なスイッチ
<label>
<input type="radio" name="foo">項目
<span>←選択中</span>
</label>
<label>
<input type="radio" name="foo">項目
<span>←選択中</span>
</label>
label { display: block; }
input + span { display: none; color: tomato; }
input:checked + span { display: inline; }
「ワニはラジオボタンでできている」
- ワニが
:checked
になったら- ワニのアニメーションを終了、クリックできないようにして、非表示にする
- ワニのラジオボタンに隣接する位置に、「痛っ」の吹き出しがあるので表示
<div id="enemy">
<input type="radio" name="enemy_1" id="enemy_1" class="enemys"><div class="effect"></div>
<input type="radio" name="enemy_2" id="enemy_2" class="enemys"><div class="effect"></div>
.enemys:checked {
overflow:hidden;
-webkit-animation-name:none;
-webkit-pointer-events: none;
pointer-events: none;
opacity:0;
}
.enemys:checked + .effect{
-webkit-animation-duration:0.5s;
-webkit-animation-iteration-count:1;
-webkit-animation-direction: normal;
}
- あらかじめスコアのほうに、ワニと対になるラジオボタンを用意しておく
- ワニにチェックが入ると、スコアの方のラジオボタンのチェックが外れる
- そうすると高さが0になってスコアがカウントアップする
<div id="score">
<input type="radio" name="enemy_1" id="score_1" class="score" checked>
<!-- 省略 -->
<input type="radio" name="enemy_10" id="score_10" class="score" checked>
<div class="score" id="score_11"></div>
</div>
<div id="enemy">
<input type="radio" name="enemy_1" id="enemy_1" class="enemys"><div class="effect"></div>
/* チェックされていないとき=ワニがチェックされたとき */
.score{
position:relative;
display:block;
width: 111px;
height: 63px;
background-color:transparent;
-webkit-appearance: button;
-moz-appearance: button;
-webkit-transition:.1s all linear;
}
/* 初期状態:高さ0 */
.score:checked{
position:absolute;
top:0px;
height:0px;
}
- ワニと対になるスコア用ラジオボタンが画像の上にある
- ワニがチェックされると、対になるスコア用のラジオボタンのチェックが外れる
- スコア用のラジオボタンが一定の高さに変化する。
- するとスプライト画像がずれてカウントアップしているように見える
- codepen
.score input {
display: block;
width: 100px;
height: 100px;
margin: 0;
outline: 1px dashed green;
transition: 0.5s height linear;
}
/* ワニがチェックされていないとき */
.score input:checked {
position: absolute;
width: 0;
height: 0;
}
<div class="score">
<div class="score_inner">
<input type="radio" name="foo-1" checked>
<input type="radio" name="foo-2" checked>
<input type="radio" name="foo-3" checked>
<svg viewBox="0 0 100 400" width="100px"><use xlink:href="#score"></use></svg>
</div>
</div>
<div class="enemy">
<label><input type="radio" name="foo-1">ワニ1</label>
<label><input type="radio" name="foo-2">ワニ2</label>
<label><input type="radio" name="foo-3">ワニ3</label>
</div>
<a
id="gameover"
href="https://s.codepen.io/geckotang/debug/wLXZvr/dGMXWdwNvRbk">
</a>
- :checkedとかで、うまいことやる?
- いやいや
- リンクをクリックさせて同じページを表示させれば...
- もう一回遊べるドン!
- 状態の管理
- プレイ画面の制限時間の管理
- ワニをクリックしたとき
- もう一度遊ぶ
- 見た目の装飾
- base64 encode dataURI
apperance
プロパティ
- 動き
- CSS Animations
- ゲームで使う画像
- ラジオボタンの見た目
- 画像のほとんどはCSSに埋め込まれている
- jsdo.itに画像をアップロードする仕組みがなかった
- なのでbase64 encodeして埋め込んだ
#gameover{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAT8A\
AAF3CAYAAADTrUyqAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbW\
...");
}
- ラジオボタン(input要素)の見た目を変えたい
appearance
プロパティを使って見た目を変えられるようにする- CSS PANICでは
-webkit-apperance: button;
を使っている。今思えばnone
でよい...
- CSS PANICでは
- 状態の管理
- プレイ画面の制限時間の管理
- ワニをクリックしたとき
- もう一度遊ぶ
- 見た目の装飾
- base64 encode dataURI
apperance
プロパティ
- 動き
- CSS Animations
ワニはこんな動きをしています。
ワニ動き職人が丁寧にひとつひとつ...
@-webkit-keyframes enemy_10{
0% {-webkit-transform:translateY(0px);}
5% {-webkit-transform:translateY(120px);}
30% {-webkit-transform:translateY(0px);}
60% {-webkit-transform:translateY(0px);}
90% {-webkit-transform:translateY(0px);}
100% {-webkit-transform:translateY(0px);}
}
#enemy_10{
-webkit-animation-name:enemy_10;
-webkit-animation-duration:10s;
-webkit-animation-delay:1s;
}
無理ゲーにならないように調整しました。
CSS PANICの話はおわり
- JSを使わないでやる必要あった?
- なにか役に立った?
- ない
- でも、当時はJSもたいして書けなかった
- JSを使わないで、いろいろできそうだったから...つい...
- 実務にそのまま使うことはない
- トリッキーな考え方は稀に実務で役に立つ
- 色々遊んだ結果、得た知識がCodeGridの原稿になったり、こうやって話してたりできた
スコアをツイートできる版をつくってみました。