この記事は CSS Advent Calendar 2019 16日目の記事です。
概要
CSSで昔懐かしのベルトスクロールゲームを作りました。
PC、画面サイズ大きめで遊んでください><
https://codepen.io/Rin_T_T/pen/MWYjJKv?editors=1100
本記事はあくまで作った物の簡単な説明のため、コード,制作過程を一部省略しています。
設計書
必須機能をまとめます。
衝突判定: hoverで判定
ゲーム画面のスクロール: transitionで実装
スタート: hoverで判定
スコア用のアイテムを設置: checkboxで実装
キャラクターの移動: カーソルを画像に置き換える。
早速作っていきます。
最初にスクロールエリアと衝突オブジェクトを作成します。
.gameArea_inner
.playArea.-test2
- for(var i = 1; i <= 50; i++)
.item.-object(class='-o' + i)
衝突判定を実装します。
.item.-objectをhoverすると兄弟要素のFailが最前面に表示するようにします。
※faile要素を最前面に維持するため、.faile要素自体にもhover状態を指定しておきます。
ひとまず判定が通ることが確認できれば良いでしょう。
.gameArea_inner
.playArea.-test2
- for(var i = 1; i <= 50; i++)
.item.-object(class='-o' + i)
+ .faile
.faile_inner
.faile_contents
.faile{position:absolute;width:100%;height:100%;z-index:-100;//初期状態では非表示display:none;//初期状態では非表示&:hover{opacity:1;z-index:100;display:block;}&_inner{display:flex;}&_contents{text-align:center;background-image:url('https://portfolio.littledemon.pw/cssadvent/failed.png');background-size:386px160px;width:100%;height:100vh;&>*{margin-top:15px;}}}.item{width:30px;height:30px;background-color:#9c290d;position:absolute;z-index:100;opacity:1;&.-object{//衝突オブジェクトクラスposition:absolute; &:hover{&~.faile{z-index:100;opacity:1;display:block;}}}}
ゲーム画面のスクロールを実装します。
.gameArea_innerのサイズをプレイエリアとし最大値を560vwに設定します。
animationを指定し、スクロールスピードを設定します。
ついでにスタート/リスタート用のanimationも作っておきます。
.gameArea{&_inner{width:560vw;display:flex;position:relative;z-index:0;left:0;animation:areaScroll70slinearforwards;}}@keyframesareaScroll{0%{position:relative;left:0vw;}100%{position:relative;left:-560vw;}}@keyframesareaScrollBack{0%{position:relative;}100%{position:relative;left:0vw;}}
スクロールを制御できるスタート/リスタートを作成します。
CSSは常に親から子へもしくは兄弟要素のみ指定できます。
スタートはスクロールしている要素と同じレイヤーに配置します。
hoverで先ほど作成したareaScrollBackを発火できるよう設定します。
+ .wrap
+ .gameArea
+ .startArea
+ .startChecker
+ .startLine
+ .startLine_text START
.gameArea_inner
.playArea
.item.-object.-ribbon.-top
.item.-object.-ribbon.-bottom
- for(var i = 1; i <= 50; i++)
.item.-object(class='-o' + i)
.startArea{display:flex;z-index:10;&:hover+.gameArea_inner{// 兄弟要素を指定し、animationを発火する。animation:areaScrollBack150seaseforwards;}}.startChecker{width:160px;background:linear-gradient(45deg,black25%,transparent25%,transparent75%,black75%),linear-gradient(45deg,black25%,transparent25%,transparent75%,black75%);background-color:white;background-size:40px40px;background-position:00,20px20px;}.startLine{background-color:white;height:100%;padding:015px;&_text{writing-mode:vertical-rl;height:100%;text-align:center;}}.gameArea{width:100%;height:100vh;background-color:white;overflow:hidden;display:flex;&_inner{~~~}}
スコア用のアイテムを作成します。
.wrap
.gameArea
.startArea
.startChecker
.startLine
.startLine_text START
.gameArea_inner
.playArea
.item.-object.-ribbon.-top
.item.-object.-ribbon.-bottom
- for(var i = 1; i <= 50; i++)
.item.-object(class='-o' + i)
+ - for(var i = 1; i <= 24; i++)
+ label.present
+ input(type="checkbox")
+ .present_item(class='-p' + i)
.present{&_item{position:absolute;width:40px;height:40px;display:block;background-size:30px30px;transition:left7s;&.-p1{//ゲームエリア上の位置(checkboxがfalseの時)top:45vh;left:20.5vw;}}&input{display:none;&:checked{&+.present_item{pointer-events:none;transition:left4s;&.-p1{//アイテムを取得した後の位置(checkboxがtrueの時)top:60vh;left:585vw;}}}}}
scssが少し複雑ですね、メインのデザインは.present_itemに担当してもらいます。
input要素は非表示にしておき、checkBoxがtureの時、後述するゴールエリアに遷移するように設定します。
キャラクターの移動
Cursolを画像に変更します。
利用できるサイズは最大128*128のようですが、
ブラウザの互換性から考えると32*32が推奨のようです。
※今回は少し小さかったため、64pxにしました。
以上で完成です。
反省点。
遊んでいただけると気づくかもしれませんが、hover要素はカーソルの移動時に現在位置を再取得します。強制スクロールというゲーム上、衝突オブジェクトの手前で停止するとhoverの判定されず貫通します。
とりあえずゴールを見たいという人はカーソル放置でゴールまでたどり着きます(笑)
スコア用のカーソル衝突オブジェクトはもっとCSS芸的なもので、頑張りたかった...時間が足りませんでした...
chrome PCのみの対応です。