STACKERゲームを作ろう その1

STACKERゲームとは?

f:id:nekorollykk:20200830224918p:plain
モヤさまinワイハーのゲーセンで出てきたゲーム

7x10のマス目の中を動く左右のブロックをタイミングよく止めて重ねていくゲーム
最初は3ブロックから始まり段々ブロック数が少なくなり最後は1ブロックになる
特定のラインまで積み重ねる事ができたらゲームクリア
(動画を見たほうが早い)
www.youtube.com

やること

  • 7x10のマス目を生成する
    nxnで自由にサイズ変えられるようにできたらCOOL
  • 指定したマスの色を変えられるようにする
  • n秒ごとに光るマスが動くようにする
    積み重ねる毎に加速するので、速さも変えられるようにするとCOOL
  • SPACEキー押下でマスをストップできるようにする
  • 下のラインと止めたマスが重なっているか判定
    重なっていないマスは消滅するようにする
  • ゴールラインを自由に決められるようにする
    nライン目まで辿り着けばクリアを変更可能に
  • マス目の光らせ方とかをオシャレにしてみる
    ゲームっぽいボヤッとした光り方にしたい

今回やったこと

7x10のマス目を生成する
完成品はこちら

ellie-app.com

1ブロックを作る

ブロックのスタイルを定義

.box {
  border: 1px solid;
  width: 50px;
  height: 50px;
}

ブロックを生成する関数

makeBox : Int -> Html Msg
makeBox boxId =
    div
        [ class "box"
        , id (String.fromInt boxId)
        ]
        []

どのマスか?が必要になるはずなのでとりあえずIDを振った

viewで呼び出す

view : Model -> Html Msg
view model =
    div []
        [ makeBox 1
        ]

これでボックスが1つ出来上がった
f:id:nekorollykk:20200909235152p:plain

指定した数ボックスを作れるようにする

指定した数のブロックを生成する関数

makeBoxByCount : Int -> List (Html Msg)
makeBoxByCount count =
    List.map makeBox (List.range 1 count)

ボックスにつけるidと指定した個数作りたかったので
List.rangeを使ってリストを作ってList.mapに渡すようにしてみた

view

view : Model -> Html Msg
view model =
    div []
        (makeBoxByCount 7)

好きな数のボックスを作れるようになった
f:id:nekorollykk:20200909235537p:plain

ボックスを横に並べてラインを作る

横並びにするスタイルを定義

.box-row {
  display: flex;
}

横並びのブロックを生成する関数

makeRow : Int -> List (Html Msg) -> Html Msg
makeRow rowId boxList =
    div
        [ class "box-row"
        , id (String.fromInt rowId)
        ]
        boxList

先程定義したbox-rowクラスを持ったdivを作成し
要素としてList (Html Msg)nこのボックスを持つようにした
どの行か?が必要になるはずなのでとりあえずIDを振った

view

view : Model -> Html Msg
view model =
    div []
        [ (makeRow 1 (makeBoxByCount 7))
        ]

横並びになった
f:id:nekorollykk:20200909235844p:plain

指定した行数のボックスのラインを作れるようにする

ボックスの個数と行数を指定してブロックを生成する関数

makeRowByCount : Int -> Int -> List (Html Msg)
makeRowByCount boxCount rowCount =
    let
        boxList =
            makeBoxByCount boxCount
    in
    List.map (\rowId -> makeRow rowId boxList) (List.range 1 rowCount)

今まで作った関数を組み合わせた
ボックスの数と行数を受け取り、各関数に渡してList (Html Msg)を作る

view

view : Model -> Html Msg
view model =
    div []
        (makeRowByCount 7 10)

好きなボックスの数と行数を指定できるようになった
f:id:nekorollykk:20200910002410p:plain

数の指定をModelで行う

Model

type alias BoxSize =
    ( Int, Int )


type alias Model =
    BoxSize


initialModel : Model
initialModel =
    ( 7, 10 )

Tupleでボックスの個数、行数を示す型を定義
initialModelで数を指定するようにした

view

view : Model -> Html Msg
view ( boxCount, rowCount ) =
    div []
        (makeRowByCount boxCount rowCount)

Tupleを展開してmakeRowByCountに渡す

これでviewは表示するだけ個数はModelの責務になった
以下は適当に数を変えてみたスクショ(8x3)
f:id:nekorollykk:20200910003227p:plain

まとめ

  • 細かく関数を作るようにしてみた
    何となくキレイにかけた感じがする
    ただbyCountだけ使いづらいような…
  • 数の指定とviewの生成をキレイに切り分けることが出来た
  • 個数の受け取りをユーザが自由に変えられるようにするのも簡単そう
    input2つとボタンを用意しておいて、受け取った値をModelに渡せばOK

サクサク?安全に書けて楽しかった
マス動かしたりする部分で悩みそうだけど、今のところとても楽しい🐊