Skip to content

Instantly share code, notes, and snippets.

@xord
Last active March 19, 2025 14:58
Show Gist options
  • Select an option

  • Save xord/ec67340a648e0511eac93ec7c76aa028 to your computer and use it in GitHub Desktop.

Select an option

Save xord/ec67340a648e0511eac93ec7c76aa028 to your computer and use it in GitHub Desktop.
2024 年度 Ruby アソシエーション開発助成金 最終報告

2024年度 Ruby アソシエーション開発助成金 最終報告

1. はじめに

この資料は、「2024 年度 Ruby アソシエーション開発助成金」制度で採択された「Processing Gem ベースの 2D レトロゲームエンジンの開発」についての最終報告書になります。

2. プロジェクト概要

昨年度採択されたCRuby 用 Processing Gem の本家 Processing との互換性向上に向けた取り組みを基に、その成果物である Processing Gem をベースにして新たに 2Dレトロゲームエンジンの開発を行いました。

このゲームエンジンは 2D のレトロゲームをターゲットとし、解像度や色数、オーディオ関連の仕様に意図的な制限を設けることでゲーム開発の複雑さを軽減し、初心者でも手軽にゲーム制作を始められる環境を提供することを目的としています。

Ruby と Processing を基盤とするこのゲームエンジンの開発により Ruby を活用したゲーム制作の幅を広げ、コミュニティの発展に貢献することを目指すものです。

3. 開発内容

本プロジェクトではレトロゲームエンジンを開発するにあたり、以下の順で開発を進めました。

  • スプライトエディター
  • マップエディター
  • 統合環境化
  • ゲーム実行機能
  • オーディオ機能実装に足りてない機能を低レイヤーに実装
  • サウンドエディター

ここからはそれぞれの開発内容について詳しく説明していきます。

3.1 スプライトエディター

本ゲームエンジンは 2Dレトロゲームを主なターゲットとしておりドット絵を基本としたゲーム制作を想定しています。そのため、まずはドット絵制作に特化したエディターを開発しました。

3.1.1 機能説明

ここでは、スプライトエディターの画面を機能ごとに説明します。

image

  1. image スプライトページ選択
    3 の「スプライト選択領域」を16ページ分保持していますので、数字横の左右ボタンで表示するページを切り替えることができます。
  2. image スプライトのサイズ選択
    8、16、32 はそれぞれドットで 8x8、16x16、32x32 を表し、ドット絵編集領域を選択したサイズに変更します。またスプライト選択領域の選択枠も、選択したサイズに合わせた大きさに変わります。
  3. スプライト選択領域
    8x8 や 16x16 の大きさのスプライト画像を敷き詰めたスプライトシートを表示します。
    各スプライト画像をクリックして選択するとドット絵編集領域に表示し、描画ツールで編集できるるようにします。
  4. ドット絵編集領域
    スプライト選択領域で選択した範囲のスプライト画像を、5 の描画ツールを使って編集します。
  5. 描画ツール
    1. image 選択ツール
      ドット絵の一部を選択し、カット・コピーしたり移動したりできます
    2. image ブラシ
      クリックした位置に、選択した色でドットを描画します
    3. image 塗りつぶし
      クリックした位置の周囲を、選択した色で塗りつぶします
    4. image 直線ツール
      ドラッグした始点と終点を、選択した色で直線を描画します
    5. image 矩形(枠線)
      ドラッグした始点と終点を矩形の左上と右下とし、選択した色で枠線を描画します
    6. image 矩形(塗りつぶし)
      ドラッグした始点と終点を矩形の左上と右下とし、選択した色で塗りつぶします
    7. image 楕円(枠線)
      ドラッグした始点と終点を楕円の左上と右下とし、選択した色で枠線を描画します
    8. image 楕円(塗りつぶし)
      ドラッグした始点と終点を楕円の左上と右下とし、選択した色で塗りつぶします
  6. カラーパレット
    描画ツールで編集する際の色を選択します。
    パレットの色については一旦この32色としていますが、このカラーパレットでゲームの印象がだいぶ変わるため、今後別の色セットに変更する可能性もあります。(現状は PICO-8 の作者が開発中の Picotron のカラーパレットをそのまま採用しています)
  7. 画面配置が未決定な機能を一時的に配置
    UI 設計上ではまだ検討中ですが、機能としては実装したものを一時的にウィンドウ右端に集めています。今後の開発でそれぞれ適切な場所に移動予定です。
    1. image ブラシサイズ選択
      ブラシツールのブラシサイズを変更します。
    2. image 物理演算の形状設定
      スプライトは内部で形状を持ち、物理エンジンによる衝突判定に利用されます。
      None、Rect、Circle がそれぞれ 物理演算なしスプライト矩形形状スプライト丸形状スプライト となります。
    3. image 物理演算の衝突の有無の設定
      Sensor を選択すると、他スプライトと接触判定はするものの形状として衝突はしない(すり抜ける)ようにすることができます

3.1.2 実装状況

レトロゲームのドット絵制作に必要となる基本的な機能はひととおり実装できました。

現時点でのスプライトエディターのソースコード

3.1.3 今後の予定

スプライトエディターとして当初予定していた基本機能は一旦実装できています。ただ、実際にゲーム開発で利用していくと欲しくなる機能がありますので、今後も継続して機能追加していく予定です。

今後実装したい機能
  • 左右、上下反転機能
  • 曲線描画ツール
  • 矩形以外の選択ツール
  • レイヤー機能
  • アニメーション関連機能

3.2 マップエディター

スプライトエディターで作成したドット絵をマップチップとして画面に配置し、RPG のフィールドやダンジョン等のマップを作成したり、横視点のプラットフォーマーゲーム向けのステージを作成する画面としてマップエディターも開発しました。

3.2.1 機能説明

ここでは、マップエディターの画面を機能ごとに説明します。

image

  1. image スプライトページ選択
    3 の「スプライト選択領域」を16ページ分保持していますので、数字横の左右ボタンで表示するページを切り替えることができます。
  2. image スプライトのサイズ選択
    8、16、32 はそれぞれドットで 8x8、16x16、32x32 を表し、配置するマップチップの大きさを変更します。
  3. スプライト選択領域
    8x8 や 16x16 などの大きさのスプライト画像を敷き詰めたスプライトシートを表示します。
    クリックで選択した部分の画像を、6 の描画ツールで 5 のマップ編集領域に配置できるようにします。
  4. image マップ選択
    マップデータは複数作成することができるので、数字横の左右ボタンで表示するマップを切り替えることができます。
  5. マップ編集領域
    3 のスプライト選択領域で選択したマップチップを、6 の描画ツールで配置してマップを編集することができます。
  6. 描画ツール
    1. image ブラシ
      マップ編集領域のクリックした位置に、選択したマップチップを配置します
    2. image 直線ツール
      マップ編集領域のドラッグした始点と終点に、選択したマップチップを直線状に配置します
    3. image 矩形(枠線)
      マップ編集領域のドラッグした始点と終点を矩形の左上と右下とし、選択したマップチップを枠線状に配置します
    4. image 矩形(塗りつぶし)
      マップ編集領域のドラッグした始点と終点を矩形の左上と右下とし、選択したマップチップを敷き詰めるように配置します

3.2.2 実装状況

2Dレトロゲームのマップ・ステージ制作に必要な最低限の機能をひととおり実装できました。

現時点でのマップエディターのソースコード

3.2.3 今後の予定

マップエディターは、ゲーム制作に必要な最低限の機能を実装しました。開発スケジュール的に優先度をさげた機能もいくつかありますので、今後も継続して機能追加していきたいと思っています。

今後実装したい機能
  • 選択ツール
  • 拡大縮小機能
  • レイヤー機能
  • 不動スプライト統合機能(負荷軽減のため)

3.3 統合環境化

スプライトエディターとマップエディターを実装した時点では起動時はどちらかの画面を固定で表示し切り替えられない状態でした。しかしレトロゲーム開発の統合開発環境とするために各エディターを切り替えながら利用できるようにする必要があります。

こちらは統合環境化実装中に、実際にスプライトエディターとマップエディターを切り替えて使う様子です。
https://x.com/tokujiros/status/1863607102314631666

3.3.1 機能説明

画面上部にナビゲーション用のバーを作り、そこに画面切り替えボタンを配置しました。

image

  1. エディター切り替えボタン
    1. image ゲーム実行画面
      ソースコードやドット絵、マップデータなどを利用してゲームの実行を開始します。
    2. image スプライトエディター画面
      スプライトエディター画面に切り替えます。
    3. image マップエディター画面
      マップエディター画面に切り替えます。
    4. image サウンドエディター画面
      サウンドエディター画面に切り替えます。

3.3.2 実装状況

各画面切り替え用のツールバーを Navigator クラスとして実装しました。

画面切り替え部のソースコード

3.4 ゲーム実行機能の開発

ゲームエンジンを統合開発環境として設計するにあたり、ゲーム実行ボタンを押すたびにソースコードを初期状態から実行できる仕組みが必要です。このため、ゲームの実行開始時には実行環境を初期化し、前回の実行状態を引き継がないよう設計しました。具体的には、無名モジュールのインスタンスを実行コンテキストとして利用し、その中でソースコードを eval することで、各実行ごとの状態を完全に分離しています。

3.4.1 実装状況

ゲーム実行のための画面表示や実行環境の管理機能などを、Runner クラスとして実装しました。

ゲーム実行機能のソースコード

3.4.2 今後の予定

ソースコードは外部テキストエディターで編集することを想定していますので、ファイルが更新されたら自動で再実行、または実行状態のままコードを反映する仕組みを導入したいと思っています。これが実現できると、ゲーム開発の効率が大幅に向上するのでぜひ実現したいところです。

またゲーム実行コンテキスト分離の実装は無名モジュールを実行コンテキストとしたことの弊害で当初ユーザー定義クラス内でユーザー定義関数が呼べなかったりといくつか問題がありました。これを解決するために method_missing を活用するなど苦しい工夫で回避していますが、ここは今後 Ruby 本体に Namespace 機能が導入されれば、実行コンテキストをネームスペースで分離できるようになるのではないかと考えており、それが可能ならばシンプルに実装し直すことができるかもしれないと期待しています。

3.5 オーディオ機能実装に足りてない機能を低レイヤーに実装

前年度に採択いただき開発した Processing Gem でひととおりの機能が揃っているグラフィックス周りとは違い、サウンドエディターとミュージックエディターの開発には事前に低レイヤーの機能追加が必要でした。

低レイヤーに実装しているオーディオ関連の機能は、サイン波や矩形波、または任意の .wav ファイルなどを鳴らすまでしかできておらず、複数の音を組み合わせて新しく効果音を作成したり、音楽を鳴らしたりする機能が足りていませんでした。

このため低レイヤー部分にシーケンサークラスを追加実装しました。

3.5.1 機能説明

Sequencer クラスのインターフェイスはシンプルです。以下のように利用します。

seq = Sequencer.new                      # シーケンサーオブジェクト作成
seq.add(Oscillator.new(freq: 440), 0, 1) # 再生開始から0秒目にラの音を1秒再生
seq.add(Oscillator.new(freq: 440), 2, 0.5) # 再生開始から2秒目にラの音を0.5秒再生
seq.add(Oscillator.new(freq: 440), 4, 0.1) # 再生開始から4秒目にラの音を0.1秒再生
Sound.new(seq, 5.1).play                   # シーケンサーオブジェクト自体を再生

シーケンサークラスに音と時間を指定して複数追加することで、指定時間通りに音を順に鳴らすことができるようになりました。

こちらは Sequencer クラスの動作確認のため、簡易的な MML コンパイラーを実装し短い音楽を鳴らしている様子です。
https://x.com/tokujiros/status/1871253335141130653

3.5.2 実装状況

C++ の低レイヤーライブラリに Sequencer クラスを実装しました。

Sequencer クラスのソースコード

3.6 サウンドエディター

レトロゲームに適したサウンドを制作するために、シンプルな音を組み合わせて効果音を作ることができるサウンドエディターも開発しました。

3.6.1 機能説明

ここではサウンドエディターの画面を機能ごとに説明します。

image

  1. image サウンド選択
    サウンドデータは複数作成することができるので、数字横の左右ボタンで表示するサウンドを切り替えることができます。
  2. image BPM 設定
    BPM (Beat Per Minute) とは1分間に刻まれる拍子の数を表す数字です。サウンドの再生スピードを設定することができます。
  3. image データ編集
    表示中のサウンドデータの中身を空にしたり、データ自体を削除することができます。
  4. サウンド編集領域
    横軸を時間、縦軸を音階として各波形の音符をブラシツール等で編集し、サウンドを制作することができます。
  5. image 再生コントロール
    編集中のサウンドを再生したり停止したすることができます。
  6. 編集ツール
    1. image ブラシ
      4 のサウンド編集領域に、6 の波形選択で選んだ波形の音符を追加します。
    2. image 消しゴム
      4 のサウンド編集領域の音符をクリックすることで削除することができます。
  7. 波形選択
    ブラシツールで追加する音の音色を選択することができます。
    1. image サイン波
      滑らかで柔らかい音。電子オルガンやフルートに似た音。
    2. image 三角波
      サイン波より少し硬いが、優しく柔らかい音。オルガンやリコーダーのような音。
    3. image 矩形波
      ビープ音やレトロゲームの音に近い、くっきりした電子音。
    4. image ノコギリ波
      鋭く力強い音。バイオリンやシンセリードのような音。
    5. image パルス波(12.5%)
      細く尖った音。鋭いビープ音のような印象。
    6. image パルス波(15%)
      12.5%よりも柔らかいが、それでも細く尖った感じ。
    7. image ノイズ 砂嵐、風、爆発音、波の音のようなノイズ系の音。

3.6.2 実装状況

レトロゲームのピコピコサウンドを手軽に制作することができるレベルまで実装することができました。

現時点でのサウンドエディターのソースコード

こちらはサウンドエディターで効果音を編集しゲーム内で鳴らす様子です。
https://x.com/tokujiros/status/1887935444580712721

3.6.3 今後の予定

サウンドエディターで効果音を作成するときに欲しい機能はまだありますので、今後も継続して機能追加していく予定です。

今後実装したい機能
  • 各音の音量の調整
  • 音色の加工機能(エンベロープ、各種フィルター、LFO など)
  • 選択と編集機能の強化

3.7 ミュージックエディター

当初はミュージックエディターも作成する予定でしたが、サウンドエディターで再生スピードを下げると音楽を作成することができることから、ほぼ同じ UI を別画面で用意する必要があるのか疑問があるため、一旦ミュージックエディターは実装しないこととしました。

音楽制作画面のつくりとしてはいろいろあり、ピアノロールをベースとしたマウス入力中心の方式、トラッカーと呼ばれる時間軸を縦に音の情報を数値で入力する方式、MML (Music Macro Language) ベースのテキスト入力方式など、レトロゲームのチップチューンを制作するのに適したインターフェイスを検討し今後改めて実装したいと思います。

4. その他の成果

ここからはメインのゲームエンジン開発以外の成果について記載します。

4.1 サンプルゲーム

このゲームエンジンでどんなゲームが作れるかを確認するため、よくあるタイプのゲームの基本部分をサンプルゲームとしていくつか制作しました。

4.1.1 横視点アクション (プラットフォーマー)

いわゆるマリオブラザーズのような横視点で重力が下方向に向いたアクションゲームです。 1つ目のロボットがプレイヤーキャラクターで左右カーソルで移動、スペースキーでジャンプ。 トゲトゲにふれるとゲームオーバです。

ソースコードは空行とコメントを除くと 82行です。

image

4.1.2 縦方向シューティング

一般的な縦シューティングゲームです。 進行方向は縦で、上から敵が来るのでカーソルキーで自機の移動とスペースキーでショットを撃ちます。

ソースコードは空行とコメントを除くと 126行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1888308304222503386

4.1.3 全方位シューティング

左右カーソルキーで自機を回転、上カーソルキーで加速、スペースキーで弾を撃ちます。

ソースコードは空行とコメントを除くと 106行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1888524579687309398

4.1.4 タワーディフェンス

ユーザーの操作は無く、設置した砲台が攻撃範囲に入った敵を自動的に攻撃します。 敵は画面右端から侵入・進行し、砲台の攻撃を耐え左端まで到達されるとゲームオーバーです。 この状態ではゲーム性がゼロですが、敵を倒したらコインをゲットしそのコインで砲台を強化するなどが考えられます。

ソースコードは空行とコメントを除くと 121行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1889025712948158569

4.1.5 トップビュー視点のレースゲーム

上下左右カーソルキーを押した方向にプレイヤーの向きが変わり、カーソルを押している間はプレイヤーのレースシップがジェット推進で直進します。 レースシップには慣性が働くため、減速する際には逆向きにジェットを噴射する必要があります。 スタート地点からゴールまでのタイムを競います。(作者のベストタイムは 8.183秒です)

ソースコードは空行とコメントを除くと 126行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1895666246785610226

4.1.6 サバイバー系ゲーム

ヴァンパイアサバイバーズという人気ゲーム風のサンプルゲームです。 カーソルキーでプレイヤーキャラクターを移動しますが、攻撃は自動で弾を撃つだけなのでプレイヤーは敵を避けることに集中します。

ソースコードは空行とコメントを除くと 159行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1895781930924462379

4.1.6 地下掘りゲーム

地面を掘って、鉱石をゲットしてスコアを稼ぐゲームです。 左右カーソルキーでプレイヤーキャラクターが移動し、スペースキーでジャンプします。 キャラクターが地面に接した方向のカーソルキーを押すと地面を掘り、金塊ブロックは三回掘ることで金をゲットすることができます。

ソースコードは空行とコメントを除くと 106行です。

image

実際にゲームが動いている様子 → https://x.com/tokujiros/status/1898807976049390028

4.2 発表

1/18 の「東京Ruby会議12」でゲームエンジンについて発表しました。

発表時には、運営中の Ruby でのゲーム開発 Discord への招待リンクを設置し 13名ほど参加いただくことができました。

4.3 動画配信

YouTube でサンプルゲーム開発の様子をライブ配信しました。

残念ながらほとんど視聴されていませんが、今後本レトロゲームエンジンでのゲーム制作 Howto 動画を制作・配信し、Ruby によるゲーム開発の敷居を下げられるようにしていきたいと思っています。

5. 課題と今後の展望

5.1 ドキュメント整備

ゲームエンジン自体は実用できるレベルになってきましたが、肝心のドキュメント類がまだ足りていません。ですので今後はリファレンスやチュートリアルなども作成し発信していく計画です。

5.2 WebAssembly 対応

ruby.wasm 対応をすることで、ゲームエンジンで作ったゲームの実行環境としてブラウザーに対応することができます。これは作ったゲームを広く手軽に遊んでもらうためにはとても大きな利点になります。特に、インストール不要でブラウザー上で即座に動作することは、ユーザーの障壁を大きく下げるため、カジュアルなプレイヤーにもリーチしやすくなります。

6. まとめ

当初計画していた開発内容はほぼ予定通り実装することができました。これによって、目的としていた通り Ruby で手軽にゲーム開発を始められるツールが制作できました。

これからはソフトウェアとしての機能強化や環境整備を継続するとともに、利用者を増やし、Ruby によるゲーム制作人口を増やすことによって Web 開発以外の用途での Ruby 利用率を増やすことにもつなげていきたいと思います。

7. さいごに

この成果を達成するためにサポートしてくださった Ruby アソシエーション様と、メンターとして支えてくださった須藤功平様に深く感謝いたします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment