14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CSSAdvent Calendar 2019

Day 16

CSSでベルトスクロールゲームを作った。

Last updated at Posted at 2019-12-15

この記事は CSS Advent Calendar 2019 16日目の記事です。

概要

CSSで昔懐かしのベルトスクロールゲームを作りました。
PC、画面サイズ大きめで遊んでください><
https://codepen.io/Rin_T_T/pen/MWYjJKv?editors=1100
本記事はあくまで作った物の簡単な説明のため、コード,制作過程を一部省略しています。

設計書

必須機能をまとめます。

衝突判定: hoverで判定
ゲーム画面のスクロール: transitionで実装
スタート: hoverで判定
スコア用のアイテムを設置: checkboxで実装
キャラクターの移動: カーソルを画像に置き換える。

早速作っていきます。

最初にスクロールエリアと衝突オブジェクトを作成します。

index.pug

    .gameArea_inner
      .playArea.-test2
        - for(var i = 1; i <= 50; i++)
          .item.-object(class='-o' + i)

衝突判定を実装します。
.item.-objectをhoverすると兄弟要素のFailが最前面に表示するようにします。
※faile要素を最前面に維持するため、.faile要素自体にもhover状態を指定しておきます。
ひとまず判定が通ることが確認できれば良いでしょう。

index.pug

    .gameArea_inner
      .playArea.-test2
        - for(var i = 1; i <= 50; i++)
          .item.-object(class='-o' + i)
        + .faile
           .faile_inner
             .faile_contents   
style.scss
.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: 386px 160px;
      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も作っておきます。

style.scss


.gameArea{
 
  &_inner{
    width: 560vw;
    display: flex;
    position: relative;
    z-index: 0;
    left: 0;
    animation: areaScroll 70s linear forwards;
  }
}

@keyframes areaScroll {
  0% {
    position: relative;
    left: 0vw;
  }
  100% {
    position: relative;
    left: -560vw;
  }
}


@keyframes areaScrollBack {
  0% {
    position: relative;
    
  }
  100% {
    position: relative;
    left: 0vw;
  }
}

スクロールを制御できるスタート/リスタートを作成します。

CSSは常に親から子へもしくは兄弟要素のみ指定できます。
スタートはスクロールしている要素と同じレイヤーに配置します。
hoverで先ほど作成したareaScrollBackを発火できるよう設定します。

index.pug

+ .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)

style.scss

.startArea{
  display: flex;
  z-index: 10;
  &:hover + .gameArea_inner{// 兄弟要素を指定し、animationを発火する。
    animation: areaScrollBack 150s ease forwards;
  }
}
.startChecker{
  width: 160px;
  background: linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%),
              linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%);
  background-color: white;
  background-size: 40px 40px;
  background-position: 0 0, 20px 20px;
}

.startLine{
  background-color: white;
  height: 100%;
  padding: 0 15px;
    &_text{
    writing-mode: vertical-rl;
    height: 100%;
    text-align: center;
  }
}


.gameArea{
  width: 100%;
  height: 100vh;
  background-color: white;
  overflow: hidden;
  display: flex;
  &_inner{
    ~~~
  }
}

スコア用のアイテムを作成します。

index.pug
 .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)

style.scss
.present{
  &_item{
    position: absolute;
    width: 40px;
    height: 40px;
    display: block;
    background-size: 30px 30px;
    transition: left 7s;
    &.-p1{//ゲームエリア上の位置(checkboxがfalseの時)
        top: 45vh;
        left: 20.5vw;
     }
  }
  & input{
    display: none;
    &:checked {
      & + .present_item {
            pointer-events: none;
            transition: left 4s;
            &.-p1{//アイテムを取得した後の位置(checkboxがtrueの時)
             top:60vh;
             left: 585vw;
        }
      }
    }
  }
}

scssが少し複雑ですね、メインのデザインは.present_itemに担当してもらいます。
input要素は非表示にしておき、checkBoxがtureの時、後述するゴールエリアに遷移するように設定します。

キャラクターの移動

Cursolを画像に変更します。
利用できるサイズは最大128128のようですが、
ブラウザの互換性から考えると32
32が推奨のようです。
※今回は少し小さかったため、64pxにしました。

以上で完成です。

反省点。

遊んでいただけると気づくかもしれませんが、hover要素はカーソルの移動時に現在位置を再取得します。強制スクロールというゲーム上、衝突オブジェクトの手前で停止するとhoverの判定されず貫通します。
とりあえずゴールを見たいという人はカーソル放置でゴールまでたどり着きます(笑)

スコア用のカーソル衝突オブジェクトはもっとCSS芸的なもので、頑張りたかった...時間が足りませんでした...

chrome PCのみの対応です。

14
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?