$30 off During Our Annual Pro Sale. View Details »

【20220920UV Study : フロントエンドLT会#7】WebAssemblyでブロック崩しを作ってみた話

【20220920UV Study : フロントエンドLT会#7】WebAssemblyでブロック崩しを作ってみた話

UV Study : フロントエンドLT会#7での発表資料です
https://uniquevision.connpass.com/event/257455/

虎の穴ラボ株式会社

September 21, 2022
Tweet

More Decks by 虎の穴ラボ株式会社

Other Decks in Technology

Transcript

  1. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. WebAssemblyでWebブロック崩 し作ってみた

    1
  2. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. アジェンダ •

    自己紹介 • 動機と話すこと • なぜRust • 作ったもの • Rust • wasm-bindgen • まとめ 2
  3. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介 3

    藤原 佳顕(ふじわら よしあき) ‣ 虎の穴ラボ ‣ Webエンジニア ‣ 新規事業担当(Fantia、Creatia)、アーキテクトチーム ‣ 前職:独立系ソフトウェア会社、主に GISとWeb、ライブラリ開発 ‣ TypeScript、C#、Ruby on Rails、C++ ‣ React、Vue、Angular ‣ 入社理由 ‣ 自分がスキルアップできそうな場所に行きたい ‣ オタク系の話ができるところに行きたい 好きなモノ ‣ シューティングゲーム、格闘ゲーム ‣ SF小説 ‣ プログラミング 自己紹介ページ(藤原)
  4. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 動機と話すこと •

    Rust+WebAssemblyでブロック崩し作ってみたので紹介 • 話すこと ◦ Rustの概要 ◦ wasm-bindgenについて ◦ 書いたソース • 話さないこと ◦ WebWorkerについて ◦ JavaScript/TypeScript側の細かいあれこれ ◦ Rustの細かい文法 ◦ ビルドツールについて 4
  5. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. なぜRust •

    Rust使いたかった(趣味) • 自分→フロントエンド得意ななんでも屋 ◦ React.js、TypeScriptとか好きです • 得意分野を消さないための種まきとして WebAssembly • Rustは公式でWebAssemblyのサポートがある ◦ wasm32-unknown-unknownターゲット • C/C++→Emscripten • Go→バイナリでかい問題 • 他 ◦ Blazor、AssemblyScript 5
  6. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 作ったもの ・MDNのCanvasブロック崩しのRust移植+α

    (https://yumenosora.co.jp/archives/tora-lab/1575) 6
  7. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 作ったもの 採用サイトからも飛べます

    (https://yumenosora.co.jp/archives/tora-lab/1575) 7
  8. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Rust •

    C++の代替を狙う低レイヤ言語 • 速度 ◦ (LLVMなので)C/C++と同程度 • パラダイム ◦ マルチパラダイム ◦ 関数型言語っぽくもオブジェクト指向っぽくも書ける • 難しい? ◦ コンパイラが優秀なので適当に怒られておけば良いと思います • 言語が出てきた当初からWebAssemblyのサポートを謳っている • WebAssemblyまつわる周辺ツール: wasm-bindgen 8
  9. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. wasm-bindgen •

    wasm-bindgen ◦ 要するにRust↔JSをやってくれるクレート(ライブラリ) ◦ Mozilla肝いり • web_sys ◦ browser APIとのつなぎ込み(DOM含む) • js_sys ◦ JSとのつなぎ込み 9
  10. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 中身(wasm-bindgen) 10

    #[wasm_bindgen] #[derive(Debug, Clone, Copy, Serialize)] pub struct Brick { x: f64, y: f64, status: BrickStatus, life: u32 } #[wasm_bindgen] impl Brick { pub fn new(x: f64, y: f64, status: BrickStatus) -> Brick { Brick { x: x, y: y, status: status, life: 1 } } } • wasm_bindgen attributeが付いている部 分がJS側にエクスポートされる • メソッドも同様にエクスポートできる import { Brick } from "mdn-breaking-blocks-wasm"; const brick = Brick.new(1, 1, 0); (Rust側) (JavaScript側)
  11. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 中身(web_sys) 11

    Web APIのインターフェース定義であるWebIDLままのI/Fが用意されている // windowがそもそも存在しない場合は unwrapでpanic let _ = web_sys::window().unwrap() .alert_with_message("YOU WIN, CONGRATULATIONS!"); let _ = web_sys::window().unwrap().location().reload(); // dyn_intoでキャスト→キャスト失敗したら map_errでエラー処理 let canvas: web_sys::HtmlCanvasElement = canvas .dyn_into::<web_sys::HtmlCanvasElement>() .map_err(|_| console::log_1(&JsValue::from_str("CanvasElement is invalid"))) .unwrap(); let context = canvas.get_context("2d") .unwrap().unwrap() .dyn_into::<web_sys::CanvasRenderingContext2d>() .unwrap();
  12. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 中身(js_sys) 12

    JavaScript APIのRustラッパーになる→世界が違うのでうまいこと動くようにされている // JavaScript側からコールバックを引数として受け取る pub fn draw_with_callback(&mut self, callback: &js_sys::Function) { for c in 0..self.bricks.len() { for r in 0..self.bricks[c].len() { if self.bricks[c][r].get_status() == BrickStatus::Live { let brick_x = c as f64 * (BRICK_WIDTH + BRICK_PADDING) + BRICK_OFFSET_LEFT; let brick_y = r as f64 * (BRICK_HEIGHT + BRICK_PADDING) + BRICK_OFFSET_TOP; self.bricks[c][r].set_x(brick_x); self.bricks[c][r].set_y(brick_y); let this = JsValue::NULL; // JavaScriptと違ってRustではコンパイル時に引数の数と型がわかっている必要がある // したがってJSの関数をそのまま呼べない (最悪applyを使う) let _ = callback.call2(&this, &JsValue::from(brick_x), &JsValue::from(brick_y)); } } } }
  13. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ 13

    • wasm-bindgenを使うことで本来は難しい WebAssemblyとJavaScriptの相互運用を行うことができます • Rustは難しいと言われていますが、基本知識 +コンパイラに従うことで書けるようになるきがします • 実は、もう1パターンの実装があります ◦ 表のレンダリングやゲーム部分 →WebAssembly ◦ 入れ替わる画像レイヤ部分 →WebWorker ◦ こちらも機会があれば喋ってみたいと思います • 今日の内容に近い内容はブログにも上げているのでぜひお読みください (http://toranoana-lab.hatenablog.com/entry/2019/08/14/190159 )
  14. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ 14