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.

小一時間でゲームをつくる の1章をReact + Typescriptで書いてみたメモ

Posted at

概要

小一時間でゲームをつくる ──7つの定番ゲームのプログラミングを体験を買ったので写経してみる。
ただ写経ではつまらないので、React + Typescriptで書いてみた。
ここでは差分についてメモを残す。

できたもの
ソースコード

レトロゲーム風フォント

8×8 ドット日本語フォント「美咲フォント」の代わりに、google fonts の DotGothic16を使用。

コンソール

コンソールの代わりにdev要素にテキストを配置して実装。

文字入力

キーボードイベントとして取得。

src/hooks/useReactHook.ts
import { useCallback, useEffect } from 'react'
export const useKeyDown = (handler: (key: string) => void) => {
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      handler(event.key)
    },
    [handler],
  )

  useEffect(() => {
    document.addEventListener('keydown', handleKeyDown)
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
    }
  }, [handleKeyDown])
}

ゲームループ

ジェネレータ関数を使用。

function* battleLoop(characters: Character[]) {
  const [player, monster] = characters
  player.target = 1
  monster.target = 0

  while (true) {
    let commandSelecting = true
    while (commandSelecting) {
      commandSelecting = yield {
        message: `${selectCommandMessage(player.command, commandNames).join(
          '\n',
        )}`,
        player,
      }
    }
    for (const c of characters) {
      switch (c.command) {
        case commands.COMMAND_FIGHT: {
          yield { message: `${c.name} の攻撃!`, player }
          const damage = Math.floor(1 + Math.random() * c.attack)
          const target = characters[c.target]
          target.hp = target.hp - damage < 0 ? 0 : target.hp - damage
          yield {
            message: `${target.name}${damage}のダメージ!`,
            player,
          }
          if (target.hp === 0) {
            return {
              message:
                player.name === 'ゆうしゃ'
                  ? 'あなたは しにました'
                  : `${target.name} をたおした!`,
              player,
            }
          }
          break
        }

      }
    }
  }
}

hooksから呼び出す。 const [gen] = useState(battleLoop(characters))

const useHooks = (characters: Character[]) => {
  const [player, monster] = characters

  const [gen] = useState(battleLoop(characters))
  const [state, setState] = useState({
    message: `${monster.name} があらわれた!`,
    player,
  })
  const selectCommand = (key: string) => {
    switch (key) {
      case 'Enter': {
        const nextState = gen.next(false).value
        if (nextState) setState(nextState)
        return
      }
    }
  }

  useKeyDown(selectCommand)

  return { state, selectCommand }
}

参考

サポートページ:小一時間でゲームをつくる ──7つの定番ゲームのプログラミングを体験

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?