0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

本題について

この記事は、自作シーティングゲーム・編集ツールのアップデート内容を毎年投稿しており、
2024年も数多くのアップデートしましたが、そのうちの一部を振り返りたいと思います

過去記事は以下になります

自作シューティングゲームとは

TypeScriptで実装したグラディウス風の横スクロールシューティングのブラウザゲームです
一部制約はありますが、基本的にPC・スマホでゲームを楽しめます
GamepadAPIを使っており、幾つかのゲームパッドやアーケードコントローラーなどと接続してゲームを楽しむこともできます

この制作目的は

  • 好きなシューティングゲームを自分で楽しむ
  • 変遷の大きいフロントエンドの技術等を学習する

です

フレームワーク React
バージョン管理 Proto
ビルド環境 Vite
テストフレームワーク Bun
言語 TypeScript
Scss
WebAPI CanvasAPI
WebAudioAPI
GamepadAPI
lintツール Biome
Stylelint
対応機種 Windows PC(Windows 11)
Mac(latest macOS)
iPhone(latest iOS)
iPad(latest iPadOS)
対応ブラウザ Chrome
Edge
Safari
接続可能外部コントローラー 8BitDo Arcade Stick
8BitDo ZEROゲームパッド コントローラー
Xbox Eliteワイヤレス コントローラー シリーズ 2
Backbone One PlayStation®版

構成

このシューティングゲームは、Nuxtで実装したステージ編集ツールと連携してます

image.png

今年も幾つか改修してますが、主だった内容だけピックアップします

1-1. 装備追加

  • HANDLE MISSILE
    ミサイル発射後、十字キーに併せてミサイルの移動先をコントロールできます
    Monosnap screencast 2024-12-27 15-39-18.gif

  • HANDLE SHIELD
    バリアを装備した時に現れたバリアが、十字キーに併せて位置が動くようになってます
    Monosnap screencast 2024-12-27 16-15-12.gif

1-2. ChatGPTを使った既存装備の改修

今年からChatGPTを使って、プロンプトから生成されたコードを参考に、
自分の実装と比較して簡潔で管理しやすいソースであればそちらに改修しました

以下の装備はChatGPTを参考に実装を変更しました

  • SWING OPTION
    OPTIONは分身装備で、ロープのように振り回す動きをします
    Monosnap screencast 2024-12-30 15-52-30.gif

1-3. 開発環境をBunに切替え

パッケージマネージャー: pnpm -> Bun

package.json
{
  ..(略)..
  "scripts": {
    "dev": "vite",
    "preview": "vite preview",
    "build": "vite build",
  }
  ..(略)..
}
# 開発環境起動
$ bun dev
# プレビュー
$ bun preview
# ビルド
$ bun run build

ユニットテスト: Vitest -> Bun

現時点でユニットテストのテストケースは2000以上ありますが、
実行は約1秒ほどでした

$ bun test
...
...
 2115 pass
 3 skip
 0 fail
 3708 expect() calls
Ran 2118 tests across 210 files. [1266.00ms]

テストソースの換装

  1. 必要なメソッドをimport
  2. vi.は全て削除
  3. it.each()はBunに併せて修正(後述)
+ import { spyOn, describe, it } from 'bun:test';

describe('case', () => {
  it('case 1', () => {
-   vi.spyOn(className, 'classMethod');
+   spyOn(className, 'classMethod'); // クラスメソッドの動作をモック
+   expect(true).toBe(true); // Bunではexpectedではなくexpect
  });
});

it.each()の変更点

Vitestでeach()メソッドはテンプレートリテラルの実装が可能で、
項目名を使ってまとまりのある見易いコードが、Bunではなぜかできない...
(調べる限り、テンプレートリテラル未対応のため、オブジェクト配列形式で記述が必要みたいです

試行錯誤の末、オブジェクト配列に変更しましたが、
Bunにもテンプレートリテラル対応が実現すれば、より便利になると感じました

+ import { describe, expect, it } from 'bun:test';

describe('getDistance', () => {
-    it.each`
-      a                  | b                 | result
-      ${{ x: 1, y: 0 }}  | ${{ x: 0, y: 0 }} | ${1}
-    `('getDistance $a, $b, $result', ({ a, b, result }) => {
+    it.each([
+      [{ x: 1, y: 0 }, { x: 0, y: 0 }, 1],
+    ])('getDistance %p, %p, %p', (a, b, result) => {
      expect(COMMON_GAME.getDistance(a, b)).toEqual(result);
    });
});

GitHub Actionsにて設定ファイルもBunに切替

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: snyk/actions/setup@master
      - uses: moonrepo/setup-toolchain@v0
        with:
          auto-install: true
-      - name: pnpm install
-        run: pnpm install
-      - name: pnpm check:all
-        run: pnpm check:all
-      - name: pnpm knip
-        run: pnpm knip
-      - name: pnpm test
-        run: pnpm test
+      - name: bun install
+        run: bun install
+      - name: bun check:all
+        run: bun check:all
+      - name: bun knip
+        run: bun knip
+      - name: bun test
+        run: bun test

先に記載したBun切替によるユニットテストがかなり貢献してくれて、
全体の実行時間も1分ほど短縮できました

Amplifyのホスティングにおけるビルド設定

こちらもBunに対応できたようで、以下に設定しました
(編集ツールも同様です)

amplify.yml
version: 1.1
frontend:
  phases:
    preBuild:
      commands:
        - curl -fsSL https://bun.sh/install | bash
        - source /root/.bashrc
        - bun install
    build:
      commands:
        - bun run build
  artifacts:
    # IMPORTANT - Please verify your build output directory
    baseDirectory: dist
    files:
      - '**/*'

2. ステージ編集ツール

Nuxtで実装したシューティングゲームのステージを作成・編集するツールです
現時点ではPCのみの対応です

フレームワーク Nuxt3
テストフレームワーク Vitest
lintツール Eslint
Prettier
Stylelint
対応機種 Windows PC(Windows 11)
Mac(latest macOS)
対応ブラウザ Chrome
Edge
Safari

編集の主な機能です

機能 操作イメージ
ステージの作成 Monosnap screencast 2023-12-30 17-02-02.gif
ステージの編集 Monosnap screencast 2023-12-30 17-05-20.gif
ステージの削除 Photos Library.gif
ステージの並替え test.gif

このステージ編集ツールは、シューティングゲームと連携しており、
ゲームを起動して、編集したステージをプレーすることができます

また、ステージの保存先は現時点で以下を対応しており、ゲーム側でクエリパラメータを使って編集したステージをプレーすることができます

リポジトリ URL
firebase https://(ゲームのパス)?repository=firebase
microCMS https://(ゲームのパス)?repository=microcms
MovableType https://(ゲームのパス)?repository=movabletype

以下に今年改修した内容を記載します

2-1. プレビュー機能

編集中のステージを実際にプレーして検証するプレビュー機能を追加しました

Monosnap screencast 2024-12-21 14-55-07.gif

プレビュー機能の概要

  • 編集中のステージをプレイして確認可能
  • Loop(難易度)や復帰位置を切り替えながらリアルタイムで確認可能
  • ゲームコントローラーを利用した操作もサポート

image.png

iframepostMessageを選択した理由

  • ゲームと編集ツールを一緒にするとプロダクトサイズが大きくなるし、総合的に管理が大変(な気がした)のを踏まえ
    • iframeを使用することで、ゲームと編集ツールを疎結合に保ちながら連携可能
    • postMessageを使うことで、異なるオリジン間でも安全にデータをやり取り可能

実装の仕組み

iframeを使ってシューティングゲームを起動し、編集ツールからステージデータをpostMessageで送信することで、プレビューを実現しています

以下図はプレビュー起動、Loop・復帰位置選択時のフローです

  • 初回プレビュー: iframeをロードし、編集中のステージデータを送信してプレビューを開始
  • Loop/復帰位置変更: 編集ツールから変更データを送信し、リアルタイムでプレビューを更新

実装例

Edit(編集ツール側)
send.vue
<template>
  <!-- シューティングゲームを表示するiframe -->
  <iframe
    ref="iframedom"
    :src="iFrameURL"
  />
  <!-- メッセージ送信ボタン -->
  <button @click.stop="sendMessage" />
</template>

<script type="ts" setup>
import { useEventListener } from '@vueuse/core'
const iframedom = ref<HTMLIFrameElement | null>(null)
const iFrameURL = computed(() => `(シーティングゲーム側のパス)`)

// 編集中のステージデータをiframeに送信
const sendMessage = () => {
  iframedom.value?.contentWindow?.postMessage(
    JSON.stringify('(送信するステージデータ)'),
    '(ゲーム側のホスト)'
  )
}

onMounted(() => {
  // iframeが読み込まれた際にメッセージを送信
  useEventListener(iframedom, 'load', () => {
    sendMessage()
  })
})
</script>
Game(ゲーム側)
recieved.ts
// ゲーム側で受信したメッセージを処理
let recievedMessage = ''
window.addEventListener('message', (event: MessageEvent<stringifiedStages>) => {
  if (event.origin === '(ステージ編集側のホスト)') {
    // 編集機能からのメッセージの場合、受信データをセット
    recievedMessage = event.data
  }
})

3. まとめ

今年も自作シーティングゲーム、ステージ編集ツールを紹介しました
2017年からシーティングゲームを作成してたので、気づいたらもう7年以上も続けてました

フロントエンドの激しい変遷の中で、
今回の体験を通じ、実務に活かせればと思ってます

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?