スタイルシート ジャンプ ゲーム の説明
戻る


JavaScript を使わず,スタイルシートだけでジャンプ ゲームを作ってみます.ジャンプして穴を飛び越えながら走るゲームです.
全くのお遊びです.これが何か実用の役に立つようなことは多分無いでしょう.スタイルシートは本来,動作を記述するものではありませんので,かなり力ずくで作っています.
画面
(これはキャプチャ画像です.これで遊ぶことはできません.)
使い方と仕組みについて説明します.


使い方

画面をクリックするとゲームを開始します.
ピクトグラム(以下「ジャンパー」という)が地面を走ります.画面をクリックするとジャンプします.
地面にはところどころ穴が開いています.穴に落ちないようにジャンプしてください.
穴を飛び越えた回数が得点として画面左上に表示されます.
穴に落ちたらゲーム終了です.ゴールはありません.ただひたすら跳び続けてください.
ゲーム終了後に画面をクリックすると,またゲームを開始します.
なお,時々上の方に現れるインベーダーのみなさんはゲームには関係ありません.


スクロールの処理

アニメーションで背景と穴をスクロールします.
ただし,無条件にスクロールしているのではなく,特定の HTML 要素が :hover 状態のときにスクロールするようにしています.それは,後述のように,ジャンパーが穴に落ちたらその要素が :hover 状態でなくなるようにして,スクロールが止まるようにしているためです.

穴の位置と大きさを 10 個分適当に決めて,スクロール位置に合わせて表示します.
アニメーションは無限に繰り返すようにして,10 個目の穴の次にはまた 1 個目の穴が表示されるというように,ゲーム終了になるまで無限に穴を表示し続けます.

アニメーションを繰り返した回数をカウントします.スクロールのアニメーションの 1 回分の時間毎にカスタム プロパティの値が 1 増えるアニメーションを実行しておきます.その値は後述のように得点の計算に使います.
また,繰り返しの 2 回目以降を判定するためにも使います.繰り返しの 2 回目以降では,穴の大きさを少し増やして難易度を上げています.


ジャンプの処理

クリックでジャンプさせるためにラジオ ボタンを二つ使います.ラジオ ボタンは非表示にしておき,各ラジオ ボタンに対してラベル(LABEL タグ)を関連付けます.
ラベルで画面全体を覆って,画面をクリックしたらラジオ ボタンがチェックされるようにします.その :checked 状態でジャンプのアニメーションを開始します.
クリックを一度検出するだけならラジオ ボタンはひとつでよいのですが,クリックを繰り返し検出したいので,ラジオ ボタンを二つ使って交互にチェックされるようにします.
ラジオ ボタンのチェック状態によってラベルの Z オーダーを変えて,一方のラジオ ボタンがチェックされているとき,もう一方のラジオ ボタンのラベルの方が前面になるようにします.ラベルをクリックする度にラベルの重なり順が入れ替わって,ラジオ ボタンが交互にチェックされるようになります.

走っているときは二つのラベルのどちらかが最前面になっているので,走っているときはラベルが :hover 状態のときにスクロールするようにします.

画面全体を覆う要素(以下「マスク要素」という)を用意して,ジャンプ中はその要素の Z オーダーを変えて最前面にします.それには二つ理由があります.
ひとつは,ジャンプ中にクリックしたときにまたジャンプしてしまわないようにするためです.ジャンプ中はマスク要素が最前面にあるので,画面をクリックしてもラベルはクリックされず,再度ジャンプすることはありません.
もうひとつは,後述のように,ジャンプ中はジャンパーが穴に落ちないようにするためです.

マスク要素を最前面にするとラベルが :hover 状態でなくなり,そのままだとスクロールが止まってしまうので,マスク要素が :hover 状態のときもスクロールするようにします.そうすることでジャンプ中もスクロールが継続します.


落下の処理

ジャンパーが穴に落ちたことを判定するために,もうひとつ画面全体を覆う要素(以下「落下判定要素」という)を用意します.ジャンパーが穴の位置に来たら,その要素の Z オーダーを変えてラジオ ボタンのラベルより前面にします.このときジャンプ中の場合は,マスク要素が最前面で落下判定要素はマスク要素より背面になるようにします.
落下判定要素が :hover 状態になったら,ジャンパーが穴に落ちるアニメーションを開始します.

ジャンパーがジャンプしないで穴の位置に来た場合は,落下判定要素が :hover 状態になりジャンパーは落下します.ラベルは :hover 状態でなくなるので,スクロールのアニメーションは停止します.
落下判定要素の重ね順 1
ジャンパーがジャンプ中に穴の位置に来た場合は,マスク要素が落下判定要素より前面になっているので,落下判定要素は :hover 状態になりません.したがってジャンパーが穴に落ちることはありません.
落下判定要素の重ね順 2
穴を飛び越えることができなくてジャンプが穴の位置で終了した場合は,その時点で,ジャンプしないで穴の位置に来たのと同じ状態になります.ジャンパーは落下し,スクロールは停止します.


得点の表示

得点の表示には CSS カウンタを使っています.CSS カウンタの一般的な使い方は,counter-reset/counter-set で値を設定して counter-increment で値を増減させるというものだと思いますが,このプログラム(?)では counter-reset で値を設定しているだけです.
スクロール位置と穴の位置・大きさから計算で,越えた穴の数を求めます.スクロールのアニメーションを繰り返して,2 回目以降のスクロール中の場合でも,これはスクロール 1 回の中での穴の数です.
スクロールを繰り返した回数と現在のスクロールでの越えた穴の数から,越えた穴の数の合計を求めます.たとえば,現在スクロールの繰り返しの 3 回目で穴を 3 個越えていたら,越えた穴の数の合計は 2×10+3 = 23 になります.
その値を counter-reset でカウンタに設定して,counter() を使って表示しています.つまり,CSS カウンタは単に数値を文字列に変換する機能として使っています.


カスタム プロパティの定義

このプログラムでは,いくつかのカスタム プロパティを @ルールの @property で定義しています.
@property の定義は,たとえばこのように書きます.
@property --a {
  syntax:'<integer>';
  inherits:true;
  initial-value:0;
}
このプログラムでは,カスタム プロパティにアニメーションを使っているところがあります.カスタム プロパティに計算値によるアニメーションを使うためには,プロパティのデータ型を定義する必要があります.
@propertysyntax<integer><number> を指定することで,そのプロパティを計算値によるアニメーション可能にしています.


このおもちゃは Opera 77 以上用に作っていますが,Google Chrome 107 で動くことが確認できています.Google Chrome の他のバージョンでの動作は未確認です.


戻る