Rust + Wasm で三角形をキャンバスに描画からの続きです。 簡単なコードメモなのであしからず。 詳細は、この本 「RustとWebAssemblyによるゲーム開発」を読もう。 (ステマとかではない。)
この Rust + Wasm で三角形をキャンバスに描画で 書いたコードに続けて記述していきます。
まず、 このピカチューらしき画像を描画するので、プロジェクトディレクトリに pikachu.png というファイル名でコピーしておきます。
現在のプロジェクト構造はこれです:
.
├── Cargo.toml
├── index.html
├── pikachu.png
└── src
└── lib.rs
src/lib.rs に pikachu.png をキャンバスに描画するコードを追記:
wasm_bindgen_futures::spawn_local(async move {
let (success_tx, success_rx) = futures::channel::oneshot::channel::<()>();
let image = web_sys::HtmlImageElement::new().unwrap();
let callback = Closure::once(move || {
success_tx.send(());
});
image.set_onload(Some(callback.as_ref().unchecked_ref()));
image.set_src("pikachu.png");
success_rx.await;
ctx.draw_image_with_html_image_element(&image, 0.0, 0.0);
});
async があるからわかるとおり非同期を使わないと画像をロードして表示できない。 詳しくは「RustとWebAssemblyによるゲーム開発」を読もう。
コード全体では次のようになります:
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let canvas = document.get_element_by_id("canvas").unwrap().dyn_into::<web_sys::HtmlCanvasElement>().unwrap();
let ctx = canvas.get_context("2d").unwrap().unwrap().dyn_into::<web_sys::CanvasRenderingContext2d>().unwrap();
let fill_color_str = format!("rgb({}, {}, {})", 238, 232, 213);
let stroke_color_str = format!("rgb({}, {}, {})", 203, 75, 22);
ctx.set_fill_style_str(&fill_color_str);
ctx.set_stroke_style_str(&stroke_color_str);
ctx.set_line_width(2.0);
ctx.move_to(150.0, 0.0);
ctx.begin_path();
ctx.line_to(0.0, 300.0);
ctx.line_to(300.0, 300.0);
ctx.line_to(150.0, 0.0);
ctx.close_path();
ctx.stroke();
ctx.fill();
wasm_bindgen_futures::spawn_local(async move {
let (success_tx, success_rx) = futures::channel::oneshot::channel::<()>();
let image = web_sys::HtmlImageElement::new().unwrap();
let callback = Closure::once(move || {
success_tx.send(());
});
image.set_onload(Some(callback.as_ref().unchecked_ref()));
image.set_src("pikachu.png");
success_rx.await;
ctx.draw_image_with_html_image_element(&image, 0.0, 0.0);
});
Ok(())
}
三角形を描画したコードのあとに画像をロードしてキャンバスに描画するコードを追加しました。
早速ビルドしてみる:
$ wasm-pack build --target web
いろいろエラーが出る。まず簡単なところから解決する:
could not find `HtmlImageElement` in `web_sys`
と言われるので Cargo.toml の該当個所に HtmlImageElement を追加:
[dependencies.web-sys]
version = "0.3.55"
features = ["Window", "Document", "HtmlCanvasElement", "CanvasRenderingContext2d", "HtmlImageElement"]
再びビルド wasm-pack build --target web 今度は:
failed to resolve: use of unresolved module or unlinked crate `futures`
futures がない、と言われた。
Cargo.toml に追記:
[dependencies]
wasm-bindgen = "0.2"
futures = "0.3.17"
wasm-bindgen-futures = "0.4.28"
dependencies セクションに futures, wasm-bindgen-futures を追加しました。
これでビルド wasm-pack build --target web すると警告がいくつか出ましたがビルドは成功しました。
web サーバーを起動して意図通りできたか確認します。
$ python3 -m http.server 8000
できました。