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では一緒に働いてくれる仲間を募集中です!
ご興味がある方は以下リンクよりご確認ください。