0
0

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 1 year has passed since last update.

VanJSでスロットゲームを作ってみた

Posted at

VanJSの勉強のために、VanJSでスロットゲームを作ってみました。Reactのカスタムフックのようなものを使ったり、コンポーネントを作って再利用できるようにしてます。ゲームとリポジトリは公開しているので、VanJSを勉強したい方は是非参考にしてください。

作成したゲーム

同じ絵柄が3つ揃ったら成功です。

リポジトリ

コード

src/main.ts
import van from 'vanjs-core'

import { Reel } from './Reel'

import { useIntervalChanger } from './useIntervalChanger'

const symbols = ['🍦', '🔔', '🍒', '🍉', '💎', '🍇', '💰', '🍀', '🍋']

const SlotGame = () => {
  const { h1, div, span, button } = van.tags

  const [intervalChanger, handler] = useIntervalChanger(symbols)
  const [intervalChanger2, handler2] = useIntervalChanger(symbols)
  const [intervalChanger3, handler3] = useIntervalChanger(symbols)

  // 絵柄の変更を開始する
  const reset = () => {
    handler.start()
    handler2.start()
    handler3.start()
  }

  // init
  reset()

  van.derive(() => {
    // どれか1つでも変更中の場合、リターン
    if (
      intervalChanger.isChanging.val ||
      intervalChanger2.isChanging.val ||
      intervalChanger3.isChanging.val
    ) {
      return
    }

    // 絵柄が全て揃った場合、アラートを表示
    if (
      intervalChanger.currentValue.val === intervalChanger2.currentValue.val &&
      intervalChanger2.currentValue.val === intervalChanger3.currentValue.val
    ) {
      alert('Congratulations!')
    }
  })

  return div(
    { class: 'slot-game' },
    h1({ class: 'title' }, 'VanJS Slot Game'),
    div(
      { class: 'order' },
      symbols.map((symbol) => span(symbol)),
    ),
    div(
      { class: 'reels' },
      Reel({
        symbol: intervalChanger.currentValue,
        stop: () => handler.stop(),
      }),
      Reel({
        symbol: intervalChanger2.currentValue,
        stop: () => handler2.stop(),
      }),
      Reel({
        symbol: intervalChanger3.currentValue,
        stop: () => handler3.stop(),
      }),
    ),
    button({ class: 'reset-btn', onclick: () => reset() }, 'RESET'),
  )
}

van.add(document.getElementById('app')!, SlotGame())

絵柄の表示とストップボタンは3つ同じなので、コンポーネントを作って再利用できるようにしました。

src/Reel.ts
import van from 'vanjs-core'
import type { State } from 'vanjs-core'

type Props = {
  symbol: State<string>
  stop: VoidFunction
}

export const Reel = ({ symbol, stop }: Props) => {
  const { div, span, button } = van.tags

  return div(
    { class: 'reel' },
    span({ class: 'reel-symbol' }, symbol),
    button(
      {
        type: 'button',
        class: 'reel-btn',
        onclick: () => stop(),
      },
      'STOP',
    ),
  )
}

絵柄の変更処理はuseIntervalChangerというReactのカスタムフックのようなものを作って、処理を再利用できるようにしました。これについては前回の記事でも取り上げているので、是非参考にしてください。

src/useIntervalChanger.ts
import van from 'vanjs-core'

import { createRandomNumber } from './utils'

export const useIntervalChanger = (items: string[]) => {
  const currentIndex = van.state(0)

  // 現在の値(絵柄)
  const currentValue = van.derive(() => items[currentIndex.val])

  // 変更中かどうか
  const isChanging = van.state(false)

  const intervalId = van.state(0)

  // 変更を開始する
  const start = () => {
    if (isChanging.val) return

    currentIndex.val = createRandomNumber(items.length)

    // 100ミリ秒毎にindexを足して値を変更
    intervalId.val = setInterval(() => {
      currentIndex.val++

      if (currentIndex.val > items.length - 1) {
        currentIndex.val = 0
      }
    }, 100)

    isChanging.val = true
  }

  // 停止する
  const stop = () => {
    clearInterval(intervalId.val)
    isChanging.val = false
  }

  return [
    { currentValue, isChanging },
    { start, stop },
  ] as const
}

まとめ

今回はVanJSでスロットゲームを作ってみました。今までVanJSでは簡単なカスタムフックしか作ったこと無かったので良い勉強になりました。コンポーネントの使いまわしで全体のコード量も減らせたので、メンテナンスしやすい形にできたのも良かったと思います。

最後に

GoQSystemでは一緒に働いてくれる仲間を募集中です!

ご興味がある方は以下リンクよりご確認ください。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?