15 个版本

0.0.15 2020 年 6 月 13 日
0.0.14 2020 年 6 月 9 日

#745WebAssembly

MIT/Apache

150KB
847

babylon.rs

docs.rs docs

Rust 中 Babylon.js 的 WebAssembly 包装器。

该项目处于预alpha阶段,API 正在积极探索。当前优先事项

  • 获取基本的 GLTF
  • 获取摄像头
  • 获取某种交互方式

该项目广泛使用 js_ffi 进行 JavaScript 绑定和 lazy_static 进行全局静态单例。

惯用语句

  • 场景包含 3D 对象
  • 材质决定 3D 对象的外观
  • 当 3D 对象下落时,它将从场景中删除

HelloWorld

use babylon::prelude::*;
#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;

lazy_static! {
    static ref GAME: Mutex<Game> = Mutex::new(Game::new());
}

struct Game {
    scene: Scene,
    shape: Vec<Sphere>,
}

impl Game {
    fn new() -> Self {
        Game {
            scene: Scene::create_from_basic_engine("#renderCanvas"),
            shape: vec![],
        }
    }
}

#[no_mangle]
pub fn main() {
    babylon::js::log("Starting demo...");
    let mut game = GAME.lock().unwrap();
    for _ in 0..10 {
        let mut sphere = Sphere::new(&game.scene, babylon::js::random());
        sphere.set_position(Vector::new(
            babylon::js::random() - 0.5,
            babylon::js::random() - 0.5,
            babylon::js::random() - 0.5,
        ));
        game.shape.push(sphere);
    }
}

在此处查看演示 这里(请务必用鼠标和箭头键 ⬅️ ⬆️ ⬇️ ➡️ 尝试!)

材质

let mut game = GAME.lock().unwrap();
for _ in 0..10 {
    let mut cube = Cube::new(
        &game.scene,
        babylon::js::random(),
        babylon::js::random(),
        babylon::js::random(),
    );
    let mut mat = StandardMaterial::new(&game.scene);
    mat.set_diffuse_color(Color::new(babylon::js::random(),babylon::js::random(),babylon::js::random()));
    mat.set_alpha(babylon::js::random());
    cube.set_material(&mat);
    cube.set_position(Vector::new(
        babylon::js::random() - 0.5,
        babylon::js::random() - 0.5,
        babylon::js::random() - 0.5,
    ));
    game.shape.push(cube);
}

在此处查看演示 这里(请务必用鼠标和箭头键 ⬅️ ⬆️ ⬇️ ➡️ 尝试!)

GLTF

let mut game = GAME.lock().unwrap();
let mut gltf = GLTF::new(&game.scene, "BoomBox.gltf");
gltf.set_scaling(Vector::new(50.0, 50.0, 50.0));

在此处查看演示 这里(请务必用鼠标和箭头键 ⬅️ ⬆️ ⬇️ ➡️ 尝试!)

100 行代码的 Pong

use babylon::prelude::*;

struct Game {
    scene: Scene,
    _camera: Camera,
    _light_1: HemisphericLight,
    _light_2: PointLight,
    ball: Sphere,
    paddle_1: Cube,
    paddle_2: Cube,
    paddle_dir: f64,
    ball_dir: Vector,
}

impl Default for Game {
    fn default() -> Self {
        let mut scene = Scene::new("#renderCanvas");
        scene.set_clear_color(Color::new(0.0, 0.0, 0.0));
        let _camera = Camera::new(&scene);
        let _light_1 = HemisphericLight::new(&scene);
        let _light_2 = PointLight::new(&scene);
        let ball = Sphere::new(&scene, 0.05);
        let mut paddle_mat = StandardMaterial::new(&scene);
        paddle_mat.set_diffuse_color(Color::new(0.5, 0.5, 0.5));
        paddle_mat.set_emmisive_color(Color::new(0.5, 0.5, 0.5));
        let mut paddle_1 = Cube::new(&scene, 0.5, 0.05, 0.05);
        paddle_1.set_position(Vector::new(0.0, 0.5, 0.0));
        paddle_1.set_material(&paddle_mat);
        let mut paddle_2 = Cube::new(&scene, 0.5, 0.05, 0.05);
        paddle_2.set_position(Vector::new(0.0, -0.5, 0.0));
        paddle_2.set_material(&paddle_mat);
        Game {
            scene,
            _camera,
            _light_1,
            _light_2,
            ball,
            paddle_1,
            paddle_2,
            paddle_dir: 0.0,
            ball_dir: Vector::new(babylon::js::random() - 0.5, -1.0, 0.0),
        }
    }
}

impl BasicGame for Game {
    fn get_scene(&self) -> &Scene {
        &self.scene
    }

    fn run(&mut self, delta_time: f64) {
        // get positions
        let p2 = self.paddle_2.get_position();
        let bp = self.ball.get_position();

        // move ball
        let b_x = self.ball_dir.x * delta_time + bp.x;
        let b_y = self.ball_dir.y * delta_time + bp.y;
        if b_x > 0.5 || b_x < -0.5 {
            self.ball_dir.x = -self.ball_dir.x;
        }

        if b_y > 0.75 || b_y < -0.75 {
            self.ball.set_position(Vector::new(0.0, 0.0, 0.0));
            self.ball_dir.x = babylon::js::random() - 0.5;
            self.ball_dir.y = -self.ball_dir.y;
        } else if b_y > 0.45 || (b_y < -0.45 && b_x <= p2.x + 0.25 && b_x >= p2.x - 0.25) {
            self.ball_dir.y = -self.ball_dir.y;
            self.ball.set_position(Vector::new(b_x, b_y, 0.0));
        } else {
            self.ball.set_position(Vector::new(b_x, b_y, 0.0));
        }

        // move opponent paddle to match ball
        self.paddle_1.set_position_x(b_x);

        // move paddle if it has velocity
        if self.paddle_dir != 0.0 {
            let p2_x = p2.x + delta_time * self.paddle_dir;
            self.paddle_2.set_position_x(p2_x)
        }
    }

    fn key_up(&mut self, _key_code: f64) {
        self.paddle_dir = 0.0;
    }

    fn key_down(&mut self, key_code: f64) {
        if key_code == 37.0 {
            self.paddle_dir = 1.0;
        } else if key_code == 39.0 {
            self.paddle_dir = -1.0;
        }
    }
}

#[no_mangle]
pub fn main() {
    run_basic_game::<Game>();
}

在此处查看演示 这里

其他演示

许可证

该项目受以下任一许可证的许可

任选其一。

贡献

除非你明确表示,否则你故意提交的任何贡献,根据 Apache-2.0 许可证定义,将如上所述双许可,不附加任何额外条款或条件。

依赖关系

~4.5MB
~84K SLoC