概述
学习一段时间rust,开始使用rust 创建一些小项目,rust的一大用处,结合JS,算法部分使用rust进行编写将编译成webassembly 后通过js调用,提高运行速度
,学习从0开始创建一个WebAssembly 游戏,学习rust如何与web 前端进行整合,该项目重点在于如何将rust编译成WebAssembly结合JS使用,至于游戏界面JS在此不进行详细介绍,直接使用模板编写。
wasm 与 wat
- 二进制格式(执行):
.wasm文件后缀
- 文本格式:
.wat文件后缀
wat 是基于文本助记表示形式WAT, wat 通过WABT工具编译成二进制文件wasm - chrome会将wasm 二进制编译成wat
- wat2wasm 网址:
项目创建
1. cargo new --lib wasm-game
2. 创建www 目录
3. 在www目录下面:
npm install --save-dev webpack-dev-server
npm install --save webpack-cli
npm install --save copy-webpack-plugin
- 加载wasm 文件必须得异步加载
wat2wasm
对于js 的使用wasm , 使用异步的方式对其进行加载
async function run() {
const response = await fetch("yz.wasm");
const buffer = await response.arrayBuffer();
// 获取web wasm
const wasm = await WebAssembly.instantiate(buffer);
// 从 wasm 获取其中方法
const addTwoFunction = wasm.instance.exports.addTwo;
const result = addTwoFunction(10, 20);
console.log(result);
}
run();
webAssembly中rust与js交互
- 前后端分离后,前端负责一部分,后端负责一部分内如,做一个互相的review
- 前往不要rust 写完部分功能后,把Trello卡片一移,交给JS这样主要树沟通成本太高。
1. 下载wasm-pack: https://rustwasm.github.io/wasm-pack/install
2. 配置crate-type
3. 配置wasm-bindgen
4. 配置wasm-opt:
[package.metadata.wasm-pack.profile.release]
wasm-opt= false
JS:
1. wasm-pack build --target web 生成包含wasm文件
2. 配置npm 的package.json 将PKG目录导入
3. 调用hello
- 第一步在Cargo.toml 配置
[package]
name = "wasm_game"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasm-bindgen = "0.2.78"
[lib]
crate-type = ["cdylib"]
// 此配置是必须的 不然会报错
[package.metadata.wasm-pack.profile.release]
wasm-opt = false
- lib.rs 中写调用jS中alert
use wasm_bindgen::prelude::*;
// rust 掉头JS
#[wasm_bindgen]
extern "C" {
// 需要在 rust中表明这个是一个外部的方法
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn hello(name: &str){
alert(name);
}
- 第二步:在当前rust目录下:
cargo build // 生成target文件
wasm-pack build --target web // 生成wasm pkg目录
- 在 js的package.json 引入刚才生成的文件
"dependencies": {
"copy-webpack-plugin": "^10.2.0",
"ts-loader": "^9.2.6",
"typescript": "^4.5.4",
"wasm_game": "file:../pkg", // 名称和lib.rs 保持一致
"webpack": "^5.66.0",
"webpack-cli": "^4.9.1"
},
npm install 重新导入, npm run dev 重新运行
效果如下在wasm中调用 js中函数
weealloc 内存分配,bootstrap.js 捕获错误
wee_alloc webassembly属于一个轻量级的内存分配器
use wasm_bindgen::prelude::*;
use wee_alloc::WeeAlloc;
#[global_allocator]
static ALLOC: WeeAlloc = WeeAlloc::INIT;
// rust 掉头JS
#[wasm_bindgen]
extern "C" {
// 需要在 rust中表明这个是一个外部的方法
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn hello(name: &str){
alert(name);
}
// 用来捕获错误
import ("./index.js").catch((e) => {
console.error("Error", e);
})
js 切换到TS
npm install typescript
npm install --save typescript ts-loader
创建画布
1.使用rust 存储蛇的长度,每个蛇的像素带你位置,向右移动 像素+1,注意边界问题
2. js 中使用canve 创建画布
3. 使用setTime 进行刷新
use wasm_bindgen::prelude::*;
use wee_alloc::WeeAlloc;
#[global_allocator]
static ALLOC: WeeAlloc = WeeAlloc::INIT;
// rust use js module
#[wasm_bindgen(module = "/www/utils/random.js")]
extern "C" {
fn random(max: usize) -> usize;
}
#[wasm_bindgen]
#[derive(Copy, Clone)]
pub enum GameStatus