ラストのまほう　第２話『RustとWASM-4の環境構築』

# 🦀Rustを書きたい（書けるとは言っていない）

WASM-4は、以下の10のプログラミング言語でゲーム開発ができます。

- AssemblyScript
- C/C++
- D
- Go
- Nelua
- Nim
- Odin
- Rust
- WAT
- Zig

なんかまったく聞いたことのない言語もありますね。NeluaやOdinというのは私はWASM-4で初めて知りました。どういう言語なんでしょうか？

このシリーズでは、プログラミング言語に Rust を使っていこうと思います。これは私が単純に一番使ってみたかった言語が Rust だからです。ちなみにシリーズ開始時点での筆者の現在のRust力は、**HelloWorldだけやったことがある**くらいです。

このシリーズの記事ではRustがどういった言語なのかについての解説はしませんが、そのかわりに**Rust初見プレイの感想**については率直に語っていきたいと思います。なお、Rustはやや難しい部類に入るプログラミング言語だそうなので、単純にゲームを作りたいだけの人は別の言語を使ったほうがいいかもしれません。

# 🛠️開発環境の構築

WASM-4のツールキットは`npm install -g wasm4`で簡単にインストールできます。これをインストールするとWASM-4の開発サーバーを起動したりビルドしたりする`w4`コマンドが使えるようになります。
プロジェクトの作成も`w4 new --rust hello-world`のようなコマンドで簡単にできます。

開発時の開発サーバーを起動するには、ターミナルから `w4 watch` コマンドを実行するだけです。`w4 watch`はファイルを編集するたびに自動で再ビルドとアプリの再読み込みまでしてくれます。ただし、記事執筆時点でやってみると`w4 watch`は`target\wasm32-unknown-unknown\debug\cart.wasm`というファイルを開こうとしており、これが見つからないのでエラーになってしまっていました。これは既知の問題のようです ([GithHubのIssue](https://github.com/aduros/wasm4/issues/521))。ひとまず `name = "cart"` とすることで起動できました。

```toml:Cargo.toml
[package]
edition = "2021"
name = "cart" # ←コレ
version = "0.1.0"
```

# 🗿`update`関数と`start`関数

チュートリアルのコードで、エントリポイントとなる `lib.rs`の中身を覗いてみます。これから作るゲームの『カートリッジ』はRustの**ライブラリクレート**となっていて、ライブラリクレートは `lib.rs`がライブラリの入口となる**クレートルートファイル**になるんだそうです。

WASM-4で最低限定義が必要な関数は `update` だけです。`update`はいわゆる「ゲームループ」で、ゲームが起動すると`update` が1秒間に60回呼び出されて、そこで自由に状態変更や描画をしていきます。それで、ゲームの状態をどこかに保存しなければいけないわけですが、`static`な変数を定義して参照しようとすると、unsafeだなんだとかいう謎のコンパイルエラーが出ます……。（※筆者はRust初心者です）

`w4 new`で作られるプロジェクトはあまりに簡素すぎて私のようなRust初心者にはつらそうだったので、こちらのチュートリアルのサンプルゲームを参考にしてみます。

https://github.com/christopher-kleine/wasm-4-tutorial-games

このプロジェクトの`update`関数のところを見てみると、こんな感じになっています。

```rust:lib.rs
lazy_static! {
    static ref GAME: Mutex<Game> = Mutex::new(Game::new());
}

#[no_mangle]
fn update() {
    GAME.lock().expect("game_state").update();
}
```

**……何これ？** `#[no_mangle]`はまあ想像がつくとしても、`lazy_static!`という謎マクロにRust初心者の私は困惑です。しかもなぜ`Mutex`……？なんかいきなりゴツい仕掛けが出てきてさらに困惑ですが、どうもRustのグローバル変数は制約が多く、動的な値で初期化できなかったり、`unsafe`になってしまうなど面倒くさいようです。これがRustの洗礼か……。まあなんかよくわかりませんが、この`Game`が`new`でインスタンス化されて`update`で更新されているということはわかるので、**細かいことは気にしない**ことにします。

また、ゲームを起動したときに一度だけ呼ばれる `start`関数も定義できます。この関数でカラーパレットを指定したりするといいようですが、ゲーム自体の初期化は今回は`Game::new`でやるので、この関数を使う機会はあまりなさそうです。

```rust:lib.rs
#[no_mangle]
fn start() {
    palette::set_palette([0xfff6d3, 0xf9a875, 0xeb6b6f, 0x7c3f58]);
}
```

ちなみに、このあと最近のRustはlazy_staticよりonce_cellのほうがイケてる！みたいな記事も見かけたので、そちらも使ってみました。確かにマクロを使わなくて若干オシャレになる気がします。まあこういう細かいことはいいんだ、先に進もう……。

```rust:lib.rs
static GAME: Lazy<Mutex<Game>> = Lazy::new(|| Mutex::new(Game::new()));

#[no_mangle]
fn update() {
    GAME.lock().expect("game_state").update();
}
```


# 🖍️試しになんか描いてみる

まあ何はともあれ何か画面に表示してみましょう。適当に四角形を描いてみます。WASM-4で矩形を書く関数は `rect` です。これを `update`メソッド内で呼び出してみます。

```rust:game.ts
pub struct Game {
}

impl Game {
    pub fn new() -> Self {
        Self { }
    }

    pub fn update(&mut self) {
        wasm4::rect(10, 10, 100, 100);
    }
}

```


`struct`とかはまあC/C++の構造体だと思えば意味がわかりますね。`impl Game`のところは、`Game`にメソッドを追加しているんだそうです。「メソッド」とはいかにもオブジェクト指向っぽい用語ではありますが、ここ最近の「ここしばらくオブジェクト指向の流行りでデータと振る舞いを『クラス』としてひとつにまとめてきたけど、**よく考えたらやっぱりデータと振る舞いは別モノなんじゃね？**」「とはいいつつも、`object.method`と打ったときにエディタで補間が出てくるのは捨てがたいよね……」という、界隈の近年の反省が生かされている気がします。

さて、これを実行するには `w4 watch`で開発サーバーを起動するのが便利です。実行すると勝手にブラウザが開き、このように表示されます。

![localhost_4444_(iPad Air) (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64695/96ee0095-b964-e9c6-e15c-4b030a2053bd.png)

160ピクセルx160ピクセルの画面のうえに、100ピクセルx100ピクセルの矩形が描かれましたね。

# 📛カラーパレットレジスタと描画色レジスタ

WASM-4では、ゲームボーイっぽい緑がかったカラーパレットがデフォルトで設定されています。このカラーパレットは `PALETTE` レジスタで設定でき、同時発色する4色を自由に選ぶことができます。例えば[公式ドキュメント](https://wasm4.org/docs/guides/basic-drawing)では次のようなコードが紹介されています。

```rust
unsafe {
    *PALETTE = [
        0xfff6d3,
        0xf9a875,
        0xeb6b6f,
        0x7c3f58,
    ];
}
```

また、`rect`などの関数で描画するときの色は `DRAW_COLORS`レジスタで制御できます。たとえば、次のようなコードだと、塗りつぶしの色にカラーパレットの`3`つめの色、枠線にカラーパレットの`4`つめの色を指定しています。

```rust
unsafe { *DRAW_COLORS = 0x42 }
rect(10, 10, 100, 100);
```


![localhost_4444_(iPad Air) (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64695/1f1af11f-f70b-7e58-2ee0-a03091b48389.png)

矩形の塗りつぶしの色が明るくなり、枠線もつきました。

こんな感じで、WASM-4のAPIは極めてシンプルで、使うのも簡単です。まあ使うの簡単だけど……いや……レジスタってさあ……。私はあまり低レベルプログラミングの経験がないので、生メモリとか生レジスタを直接触る経験がありません。でもWASM-4は非常に簡素な組み込みハードウェアを模していて、生のフレームバッファとかを直接触れて生のメモリ破壊とかが普通に起こります。JavaVMやJavaScriptランタイムの温室で育ったワイには過酷だよ……。このあたりの**WASM-4の生っぷり**は後々紹介していきたいと思います。



# 🔜次回予告

次回はどんなゲームを作っていくのかという計画を立てていきたいと思います。計画を立てて常に完成を視野に入れながら動かないと、だらだらと開発を続けることになってしまうので……。個人ゲーム開発では「何を作るか」より「何を作らないか」のほうが大事かもしれません。もちろん時間と能力と根気が許すなら商業AAAゲームにも劣らない神ゲーを作りたいですが、個人ゲーム開発では何もかもが足りないのです。



https://qiita.com/hiruberuto/items/ba1e1d441c1fff98ca77