Rustのゲーム開発:Bevy・Macroquadほか
ゲームを作りたくてRustを学び始める人はたくさんいます。すばらしい理由です! ゲームには速さと、メモリの慎重な使い方と、ボス戦の途中でクラッシュしないコードが必要です。そしてそれは、まさにRustが得意とすることです。
このページでは、ありのままの姿をお見せします。Rustですでにどんなものが作られているのか、どのエンジンやライブラリを選べばいいのか、そしてほとんどのゲームが使う2つの考え方、ゲームループとECSです。そのあと、BevyとMacroquadで最初のプログラムを見ていきます。
どの例がどこで動く? ゲームループ、小さなECSの世界、そして練習問題はふつうのRustなので、Rust Playgroundで動かせる「▶ 実際に試してみよう」ボタンがあります。BevyとMacroquadはウィンドウを開くので、それらの例は自分のパソコンで cargo run して試すためのものです。Macroquadの例はこのページを書くときに実際にコンパイルしました(Web向けにも)。Bevyの例はBevyの公式のサンプルに沿っています。
Rustのゲーム開発の正直な現状
Section titled “Rustのゲーム開発の正直な現状”コミュニティのサイトAre We Game Yet?(英語)は、Rustのゲームのエコシステムを追いかけています。サイト名の問いに対する答えは「Almost. We have the blocks, bring your own glue.」(もう少し。部品はそろっているから、つなぎは自分で持ってきて)です。うまいまとめだと思います。
今の時点でよいところ:
- 本物のゲームがリリースされています。 Steamで配信されている、のんびりお城を作るゲームのTiny Gladeと、オープンソースのボクセルRPGのVelorenは、どちらもAre We Game YetにRustのゲームとして載っています。
- 強力なエンジンがあります。 Bevyには大きく活発なコミュニティがあり、数か月ごとに新しいリリースが出ます。
- 部品がたくさんあります。 Are We Game Yetには、物理演算、オーディオ、入力、ネットワーク、UIなどのクレートが並んでいます。
- ゲームをWebでも動かせます。 RustはWebAssemblyにコンパイルできるので、多くのRustのゲームはブラウザでも動きます。
まだ大変なところ:
- 「RustのUnity」はまだありません。 Rustのエンジンのほとんどはコードが中心です。ビジュアルエディタもあります(Fyroxにはエディタがあり、GodotではRustを使えます)が、大手の商用ツールと比べるとまだ若いです。
- どんどん変わります。 Bevyはまだ1.0より前で、リリースのたびに破壊的変更があります。去年のチュートリアルは、もうコンパイルできないかもしれません。
- コンパイル時間。 大きなエンジンは、最初のビルドに数分かかります。対策はこのページの後半で紹介します。
アーティストのチームと一緒に来年商用の3Dゲームを出すのが目標なら、Unity、Unreal、Godotのほうが安全です。学ぶため、2Dゲーム、ゲームジャム、ツールやシミュレーションを作るため、あるいは単にRustが好きだからというのなら、とても楽しい場所です。🦀
どのエンジン・ライブラリを選ぶ?
Section titled “どのエンジン・ライブラリを選ぶ?”道具には2種類あります。エンジンは全体の構造を用意してくれます。ゲームのオブジェクト、シーン、アセットがどう動くかまで決まっています。ライブラリ(またはフレームワーク)は、ウィンドウ、描画、サウンド、入力を用意してくれて、残りは自分で組み立てます。
| クレート | どんなものか | 向いていること | 知っておきたいこと |
|---|---|---|---|
bevy(0.20) |
ECSを中心に作られた2D・3Dの本格的なエンジン | 大きめのプロジェクト、3D、最近のエンジンのしくみを学ぶこと | いちばん有名なRustのエンジン。リリースごとに破壊的変更があり、最初のビルドが長い |
macroquad(0.4) |
raylibに影響を受けたシンプルな2Dライブラリ | はじめてのゲーム、ゲームジャム、Webゲーム | 依存クレートがとても少なく、ビルドが速い。ループの中で描画関数を呼ぶ |
ggez(0.10) |
LÖVEに影響を受けた軽量な2Dフレームワーク | 構造がはっきりした2Dゲーム | update と draw を持つ EventHandler トレイトを実装する |
fyrox(1.0) |
シーンエディタ付きの2D・3Dエンジン | GodotやUnityのようなエディタがほしい人 | 2026年にバージョン1.0になった。コミュニティはBevyより小さい |
raylib(6.0) |
CのライブラリraylibへのRustバインディング | Cでraylibを使ったことがある人 | Cのライブラリをビルドするので、CMakeとCのビルドツールが必要(FFIを参照) |
godot(0.5、「gdext」) |
Godot 4エンジン用のRustバインディング | Godotのエディタを使いつつ、ゲームのロジックをRustで書くこと | GodotがGDExtensionとして読み込むRustのクラスを書く |
シンプルなルール: はじめての2DゲームならMacroquadから始めましょう。本格的なエンジンがほしくて、ECSを学ぶのも楽しめるならBevyです。エディタで見ながら物を配置したいなら、Godot + gdextかFyroxを選びましょう。
ゲームループ
Section titled “ゲームループ”ほとんどすべてのゲームは、終了するまで何度もくり返し実行される、1つの大きなループです。
- 入力を読む(キー、マウス、コントローラー)。
- ゲームを更新する:物を動かし、衝突を調べ、点数を数えます。
- 新しい絵を画面に描く。
ループの1回をフレームと呼びます。1秒間に60フレーム(60 FPS)なら、1フレームの持ち時間は約16ミリ秒です。でも、すべてのフレームが同じ時間で終わるわけではありません。パソコンが忙しいこともあれば、あるフレームでファイルを読み込む必要があることもあります。
ゲームがプレイヤーを「毎フレーム2ずつ」動かすと、速いパソコンでは速く、遅いパソコンでは遅く動いてしまいます。よく使われる解決策が固定タイムステップ(fixed timestep)です。ゲームのロジックはいつも同じ幅(ここでは10ミリ秒)ずつ進み、各フレームでは、経過した時間に収まるだけのステップを実行します。余った時間は、次のフレームまでアキュムレータ(accumulator)にためておきます。
const STEP_MS: u32 = 10; // ゲームのロジックはいつも10ミリ秒ずつ進むconst SPEED: i32 = 2; // プレイヤーは1回の更新で2だけ動く
fn main() { // 各フレームに実際にかかった時間。本物のゲームでは時計で計る let frame_times = [16, 16, 45, 5, 16, 33];
let mut accumulator = 0; // 経過したけれど、まだシミュレーションしていない時間 let mut position = 0;
for (frame, elapsed) in frame_times.into_iter().enumerate() { accumulator += elapsed;
// 手元の時間に収まるだけ、固定のステップを実行する let mut updates = 0; while accumulator >= STEP_MS { position += SPEED; // update():ゲームのロジック accumulator -= STEP_MS; updates += 1; }
// render():何が起きても、描画は1フレームに1回 println!("frame {frame}: {elapsed:>2} ms, {updates} update(s), player at {position:>2}, {accumulator} ms left over"); }}実行結果:
frame 0: 16 ms, 1 update(s), player at 2, 6 ms left overframe 1: 16 ms, 2 update(s), player at 6, 2 ms left overframe 2: 45 ms, 4 update(s), player at 14, 7 ms left overframe 3: 5 ms, 1 update(s), player at 16, 2 ms left overframe 4: 16 ms, 1 update(s), player at 18, 8 ms left overframe 5: 33 ms, 4 update(s), player at 26, 1 ms left overフレーム2を見てください。このフレームは遅かった(45ミリ秒)ので、ゲームは追いつくために4回更新しています。全部で131ミリ秒が経過し、ゲームは10ミリ秒の更新を13回実行しました。時間がどんなふうにフレームに分かれても、プレイヤーは最後に26の位置にいます。そのため物理演算が安定し、どのパソコンでも同じ動きになります。これはリプレイやオンラインゲームでも大切です。ひとつ危険なのは、あるフレームがとても遅いと、追いつくためにたくさん更新して、次のフレームまで遅くなってしまうことです。そのため本物のループでは、1フレームあたりの更新回数に上限も設けます(たとえばBevyのゲーム時計は、標準では1フレームで最大250ミリ秒しか進みません)。
もうひとつのよくある方法がデルタタイム(delta time)です。前のフレームからの秒数を計り、速さにそれを掛けます(x += speed * dt)。こちらのほうがシンプルで、下のBevyとMacroquadの例もこの方法を使っています。多くのエンジンは両方を使います。アニメーションにはデルタタイム、物理演算には固定ステップ、という具合です。
ECSとは:エンティティ、コンポーネント、システム
Section titled “ECSとは:エンティティ、コンポーネント、システム”多くの言語では、Player クラスを作り、Character を継承した Enemy クラスを作り……と進めていくでしょう。でも、これはすぐにややこしくなります。拾うこともできる敵はどうしましょう? そこでRustのゲームエンジンのほとんどは、代わりにECS(Entity Component System)を使います。
- エンティティ(entity)は、番号のようなただのIDです。それ自身はデータも振る舞いも持ちません。
- コンポーネント(component)は、エンティティに付けるただのデータです。
Position、Velocity、Healthなどです。Rustではふつうの構造体や列挙型です。 - システム(system)は、特定のコンポーネントを持つすべてのエンティティに対して実行される関数です。たとえば移動のシステムは、
PositionとVelocityの両方を持つものすべてを処理します。
木は Position を持っていますが、Velocity は持っていないので、移動のシステムは木を飛ばします。木を動かしたい? それなら Velocity を付けるだけです。クラスを書き換える必要はありません。データと振る舞いが分かれていて、これはRustの借用のルールともよく合います。
ふつうのRustで作った、小さなECSの世界を見てみましょう。コンポーネントの種類ごとに専用のベクタがあり、エンティティのIDはそのインデックスです。None は「このエンティティはそのコンポーネントを持っていない」という意味です(Optionを参照)。
struct Position { x: i32, y: i32 }struct Velocity { dx: i32, dy: i32 }
// エンティティはただのID:すべてのコンポーネントのリストへのインデックスtype Entity = usize;
#[derive(Default)]struct World { names: Vec<&'static str>, positions: Vec<Option<Position>>, velocities: Vec<Option<Velocity>>,}
impl World { fn spawn(&mut self, name: &'static str, pos: Option<Position>, vel: Option<Velocity>) -> Entity { self.names.push(name); self.positions.push(pos); self.velocities.push(vel); self.names.len() - 1 }}
// システム:Position と Velocity の「両方」を持つすべてのエンティティを処理するfn movement_system(world: &mut World) { for (pos, vel) in world.positions.iter_mut().zip(&world.velocities) { if let (Some(pos), Some(vel)) = (pos, vel) { pos.x += vel.dx; pos.y += vel.dy; } }}
// もうひとつのシステム:Position を持つすべてのエンティティを表示するfn print_system(world: &World, tick: u32) { println!("tick {tick}:"); for (id, pos) in world.positions.iter().enumerate() { if let Some(pos) = pos { println!(" #{id} {:<6} at ({}, {})", world.names[id], pos.x, pos.y); } }}
fn main() { let mut world = World::default(); world.spawn("player", Some(Position { x: 0, y: 0 }), Some(Velocity { dx: 1, dy: 0 })); world.spawn("tree", Some(Position { x: 5, y: 2 }), None); // Velocity がない:決して動かない world.spawn("arrow", Some(Position { x: 0, y: 3 }), Some(Velocity { dx: 3, dy: -1 }));
for tick in 1..=2 { movement_system(&mut world); print_system(&world, tick); }}実行結果:
tick 1: #0 player at (1, 0) #1 tree at (5, 2) #2 arrow at (3, 2)tick 2: #0 player at (2, 0) #1 tree at (5, 2) #2 arrow at (6, 1)名前は {:<6} で幅をそろえて表示しているので、英語のままにしています(日本語の文字は画面上で2文字分の幅になり、そろわなくなるためです)。
木は Velocity を持っていないので、(5, 2) にとどまります。誰も「木は動かない」とは書いていません。データからそうなるだけです。本物のECSライブラリはこれよりずっと速く賢くできています(CPUがすばやく読めるようにコンポーネントを並べて保存し、システムを並列に実行します)が、考え方は同じです。
はじめてのBevyアプリ
Section titled “はじめてのBevyアプリ”Bevy(英語)はいちばん有名なRustのエンジンで、すべてがECSでできています。バージョン0.20は2026年10月に出ました。Bevyには最新のstable版のRustが必要なので、まずアップデートしてから、プロジェクトを作りましょう。
rustup updatecargo new my_bevy_gamecd my_bevy_gamecargo add bevyLinuxでは、いくつかのシステムライブラリ(サウンド、入力、グラフィックス)も必要です。Bevyのセットアップガイド(英語)に、ディストリビューションごとの一覧があります。WindowsではVisual StudioのC++ビルドツール、macOSではXcodeのコマンドラインツールが必要です。
このプログラムは、Bevyの公式サンプル 2d/move_sprite をもとにしています。オレンジ色の四角が左右に滑るように動きます(公式のサンプルは画像を読み込みますが、ここでは画像ファイルがいらないように、ただの色付きの四角を使っています)。
use bevy::prelude::*;
fn main() { App::new() .add_plugins(DefaultPlugins) // ウィンドウ、描画、入力、オーディオ…… .add_systems(Startup, setup) // 最初に1回だけ実行される .add_systems(Update, sprite_movement) // 毎フレーム実行される .run();}
// コンポーネント:このエンティティがどちらに動いているか#[derive(Component)]enum Direction { Left, Right,}
fn setup(mut commands: Commands) { commands.spawn(Camera2d);
// 3つのコンポーネントを持つエンティティを1つ作る commands.spawn(( Sprite::from_color(Color::srgb(1.0, 0.5, 0.2), Vec2::new(50.0, 50.0)), Transform::from_xyz(0.0, 0.0, 0.0), Direction::Right, ));}
// システム:Direction と Transform の「両方」を持つすべてのエンティティで実行されるfn sprite_movement(time: Res<Time>, mut sprite_position: Query<(&mut Direction, &mut Transform)>) { for (mut logo, mut transform) in &mut sprite_position { match *logo { Direction::Right => transform.translation.x += 150. * time.delta_secs(), Direction::Left => transform.translation.x -= 150. * time.delta_secs(), }
if transform.translation.x > 200. { *logo = Direction::Left; } else if transform.translation.x < -200. { *logo = Direction::Right; } }}上の小さなECSの世界と比べてみてください。#[derive(Component)] は、ふつうの列挙型をコンポーネントにします。commands.spawn((...)) は、コンポーネントのタプルを持つエンティティを作ります。そして Query<(&mut Direction, &mut Transform)> はBevyに「両方を持つすべてのエンティティ」を頼んでいます。私たちの movement_system が zip でやっていたのと同じです。time.delta_secs() はゲームループのセクションで見たデルタタイムなので、どのパソコンでも四角は1秒間に150ピクセル動きます。
cargo run で実行します。最初のビルドでは数百個のクレートをコンパイルするので数分かかることがあります。気長に待ちましょう。そのあとのビルドはずっと速くなります。
Bevyのコンパイル(と実行)を速くする
Section titled “Bevyのコンパイル(と実行)を速くする”Bevyのセットアップガイドは2つのことをすすめています。1つ目は、Cargo.toml に次の設定を追加することです。Bevyとほかの依存クレートを最適化しつつ、自分のコードはすばやくコンパイルできるようにします。
[dependencies]bevy = "0.20"
# Enable a small amount of optimization in the dev profile.[profile.dev]opt-level = 1
# Enable a large amount of optimization in the dev profile for dependencies.[profile.dev.package."*"]opt-level = 3これがないと、ゲームのデバッグビルドはとても遅くなることがあります。フレームレートが低く、読み込みにも時間がかかります。依存クレートのコンパイルは一度だけなので、最適化のコストを払うのは最初のビルドのときだけです(プロファイルについてはパフォーマンスで説明しています)。
2つ目は、開発中は dynamic_linking フィーチャーをオンにすることです。するとBevyは別の共有ライブラリとしてビルドされるので、変更のたびにCargoがBevy全体をあなたのプログラムにリンクし直す必要がなくなります。
cargo run --features bevy/dynamic_linkingBevyのガイドには注意が2つあります。Windowsでは、dynamic_linking は上の opt-level の設定と一緒でないと動きません。そして、この設定のままゲームを配布しないでください。ゲームの横に追加のライブラリファイルが必要になってしまいます。リリース版はこのフィーチャーなしでビルドしましょう。ガイドでは、より速いリンカ(lld や mold)の使い方も紹介されていて、特にLinuxで大きな効果があります。
Macroquadのウィンドウ
Section titled “Macroquadのウィンドウ”Macroquad(英語)は、雰囲気がまったく違います。ECSもアプリビルダーもありません。ゲームループは自分で書き、draw_circle のようなシンプルな関数で描画します。依存クレートがとても少ないので、まっさらな状態からのビルドも数分ではなく数秒で終わります。
cargo new move_the_ballcd move_the_ballcargo add macroquad[dependencies]macroquad = "0.4"この小さなゲームでは、矢印キーでボールを動かせます。
use macroquad::prelude::*;
#[macroquad::main("Move the Ball")]async fn main() { let mut player = vec2(screen_width() / 2.0, screen_height() / 2.0); let speed = 250.0; // 1秒あたりのピクセル数
loop { // 1. 入力:矢印キーでプレイヤーを動かす let dt = get_frame_time(); // 前のフレームからの秒数 if is_key_down(KeyCode::Right) { player.x += speed * dt; } if is_key_down(KeyCode::Left) { player.x -= speed * dt; } if is_key_down(KeyCode::Down) { player.y += speed * dt; } if is_key_down(KeyCode::Up) { player.y -= speed * dt; } if is_key_pressed(KeyCode::Escape) { break; }
// 2. プレイヤーを画面の中にとどめる player.x = player.x.clamp(0.0, screen_width()); player.y = player.y.clamp(0.0, screen_height());
// 3. このフレームのすべてを描く clear_background(DARKBLUE); draw_circle(player.x, player.y, 20.0, ORANGE); draw_text("Arrow keys to move, Esc to quit", 20.0, 30.0, 28.0, WHITE);
next_frame().await }}ゲームループの3つのステップ、入力・更新・描画が見えますね。#[macroquad::main("Move the Ball")] は、そのタイトルのウィンドウを開きます。main は async ですが、Tokioもasyncの知識も必要ありません。next_frame().await は単に「このフレームを表示して、次のフレームを待つ」という意味です。Linuxでは、MacroquadのREADMEに、先にインストールしておくシステムパッケージがいくつか挙がっています(Ubuntuなら pkg-config libx11-dev libxi-dev libgl1-mesa-dev libasound2-dev)。
Webで動くゲーム(WebAssembly)
Section titled “Webで動くゲーム(WebAssembly)”MacroquadもBevyも、ゲームをブラウザ向けのWebAssemblyとしてビルドできます。Wasmがはじめてなら、先にRustとWebAssemblyを読んでください。どちらの場合も、まずWasmのターゲットを追加します。
rustup target add wasm32-unknown-unknownMacroquadなら、とても簡単です。コマンド1つで .wasm ファイルができます。
cargo build --release --target wasm32-unknown-unknownファイルは target/wasm32-unknown-unknown/release/move_the_ball.wasm にできます(上の例では約600 KBでした)。MacroquadのREADMEには、小さなJavaScriptファイル mq_js_bundle.js を使ってそれを読み込む、短い index.html が載っています。両方のファイルを1つのフォルダに入れ、好きなローカルWebサーバーで配信しましょう。たとえば basic-http-server . です(cargo install basic-http-server でインストールできます)。HTMLファイルをダブルクリックするだけでは、たいていうまくいきません。ブラウザが、ディスクから直接 .wasm ファイルを読み込むのをブロックするからです。
Bevyは、JavaScriptとのつなぎのコードを作るのに wasm-bindgen を使います。次の手順は、BevyのexamplesのREADMEをもとにしています(上の my_bevy_game プロジェクトの場合)。
cargo install wasm-bindgen-clicargo build --release --target wasm32-unknown-unknownwasm-bindgen --out-dir web --target web target/wasm32-unknown-unknown/release/my_bevy_game.wasmこれで web フォルダに .js ファイルと _bg.wasm ファイルができます。小さなHTMLページが .js ファイルを読み込んで、ゲームを始めます。Bevyのセットアップガイドでは、ダウンロードを小さくするために opt-level = "s" を使う wasm-release プロファイルもすすめています。Web版のビルドは、ゲームジャムの作品を共有するのにぴったりです。みんながワンクリックで遊べて、何もインストールする必要がありません。
よくある間違い
Section titled “よくある間違い”毎フレーム決まった量だけ動かす。 毎フレーム x += 5.0 とすると、120 FPSでは60 FPSのときの2倍の速さでゲームが進んでしまいます。デルタタイムを掛ける(x += speed * dt)か、固定タイムステップを使いましょう。
古いBevyのチュートリアルどおりに書く。 BevyはリリースのたびにAPIが変わるので、0.12向けのブログ記事は0.20ではコンパイルできないことがよくあります。チュートリアルがどのバージョン向けかを確かめ、自分のバージョンの公式サンプルを優先しましょう。リリースごとに、Bevyのサイトには移行ガイドもあります。
デバッグビルドが遅い。 Bevyのゲームが数フレーム毎秒でしか動かないなら、たぶん Cargo.toml の opt-level の設定を忘れています。
いきなり大きく始める。 オープンワールドのRPGは、どの言語でもはじめてのプロジェクトには難しすぎます。Pong、Snake、ブロック崩し、Flappy Birdから始めましょう。まず完成させて、次のものを少しだけ大きくすればいいのです。
1. 列挙型でゲームの状態を表す
Section titled “1. 列挙型でゲームの状態を表す”どのゲームにも画面があります。メニュー、ゲーム本体、ポーズ画面、「ゲームオーバー」です。Menu、Playing、Paused、GameOver を持つ列挙型 GameState と、Enter、Escape、PlayerDied を持つ列挙型 Input を作ってください。そして fn next_state(state: GameState, input: Input) -> GameState を書きましょう。メニューでEnterを押すとゲームが始まり、Escapeでポーズと再開を切り替え、プレイヤーがやられるとゲームオーバーになり、「ゲームオーバー」でEnterを押すとメニューに戻ります。それ以外の入力では何も変わりません。決まった入力のリストを順番に与えて、変化を1つずつ出力してください。ヒント: タプル (state, input) に対してmatchを使い、最後を (same, _) => same で締めくくりましょう。
解答を見る
#[derive(Debug, Clone, Copy)]enum GameState { Menu, Playing, Paused, GameOver,}
#[derive(Debug, Clone, Copy)]enum Input { Enter, Escape, PlayerDied,}
fn next_state(state: GameState, input: Input) -> GameState { match (state, input) { (GameState::Menu, Input::Enter) => GameState::Playing, (GameState::Playing, Input::Escape) => GameState::Paused, (GameState::Paused, Input::Escape) => GameState::Playing, (GameState::Playing, Input::PlayerDied) => GameState::GameOver, (GameState::GameOver, Input::Enter) => GameState::Menu, // それ以外:入力を無視して、今の状態のままにする (same, _) => same, }}
fn main() { use Input::*; // Input::Enter の代わりに Enter と書けるようにする let inputs = [Escape, Enter, Escape, PlayerDied, Escape, PlayerDied, Enter];
let mut state = GameState::Menu; for input in inputs { let new_state = next_state(state, input); println!("{state:?} + {input:?} -> {new_state:?}"); state = new_state; }}実行結果:
Menu + Escape -> MenuMenu + Enter -> PlayingPlaying + Escape -> PausedPaused + PlayerDied -> PausedPaused + Escape -> PlayingPlaying + PlayerDied -> GameOverGameOver + Enter -> Menuタプルでマッチすると、許される変化がすべて1か所に並びます。そして最後のアームが、それ以外のすべての入力を無害にしてくれます。ポーズ中のプレイヤーはやられません。(Paused, PlayerDied) は (same, _) に当てはまるからです。Bevyにも同じ考え方が States という名前で組み込まれています。
- Rustはゲーム開発の本当の選択肢です。「もう少し」の段階ですが、強力なエンジン(Bevy)、シンプルなライブラリ(Macroquad、ggez)、エディタを使える選択肢(Fyrox、Godot + gdext)、そしてたくさんの部品があります。
- どのゲームもループを回しています。入力、更新、描画です。デルタタイムか固定タイムステップを使えば、速さがフレームレートに左右されません。
- ECSはゲームを、エンティティ(ID)、コンポーネント(ただのデータ)、システム(特定のコンポーネントを持つエンティティに対して実行される関数)に分けます。
- Bevyは隅から隅までECSです。
opt-levelのプロファイル設定を追加し、dynamic_linkingは開発中だけ使いましょう。 - Macroquadは2Dゲームをいちばん早く始められます。ループは自分で書き、シンプルな関数で描画します。
- どちらも
wasm32-unknown-unknownターゲットでブラウザ向けにビルドできます。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. ECSで、エンティティとは何ですか?
2. 固定タイムステップを使うと、どのパソコンでもゲームが同じように動くのはなぜですか?
3. 完成したゲームを配布するときに、オンにしたままにしては「いけない」Bevyの設定はどれですか?
4. ビルド時間がとても短い、はじめての小さな2Dゲームを作りたいとき、このページがすすめているクレートはどれですか?
スコア: 0 / 4
さらに詳しく
Section titled “さらに詳しく”- Are We Game Yet?(英語):Rustのゲームエンジン、物理演算・オーディオ・ネットワークのライブラリ、Rustで作られたゲームをまとめたコミュニティのサイトです。
- Bevy Quick Start: Setup(英語):Bevyのインストール、コンパイルを速くする設定、リリース用とWasm用のプロファイルについての公式ガイドです。
- Game development in Rust with Macroquad(英語):Macroquadで本格的なシューティングゲームを1ステップずつ作っていく、無料のオンラインブックです。
- The godot-rust book(英語):gdextを使って、Godot 4のゲームロジックをRustで書く方法。
- Game Loop — Game Programming Patterns(英語):ゲームループ、デルタタイム、固定タイムステップを、親しみやすく詳しく説明しています。