Initial commit
This commit is contained in:
commit
313b188873
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
pkg
|
||||
target
|
147
Cargo.lock
generated
Normal file
147
Cargo.lock
generated
Normal file
@ -0,0 +1,147 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "game"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
25
Cargo.toml
Normal file
25
Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "game"
|
||||
version = "0.1.0"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3.51"
|
||||
wasm-bindgen = "0.2.74"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
features = [
|
||||
'CanvasRenderingContext2d',
|
||||
'Document',
|
||||
'Element',
|
||||
'Event',
|
||||
'KeyboardEvent',
|
||||
'HtmlCanvasElement',
|
||||
'HtmlImageElement',
|
||||
'Window',
|
||||
]
|
8
Makefile
Normal file
8
Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
all:
|
||||
wasm-pack build --target web
|
||||
|
||||
deploy: all
|
||||
ssh pi -C "rm -rf /mnt/www/storage.tforgione.fr/game"
|
||||
ssh pi -C "mkdir /mnt/www/storage.tforgione.fr/game"
|
||||
scp index.html pi:/mnt/www/storage.tforgione.fr/game
|
||||
scp -r static pkg pi:/mnt/www/storage.tforgione.fr/game
|
21
index.html
Normal file
21
index.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
|
||||
<style>
|
||||
* {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<script type="module">
|
||||
import init from './pkg/game.js';
|
||||
async function run() { await init(); }
|
||||
run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
141
src/engine/event.rs
Normal file
141
src/engine/event.rs
Normal file
@ -0,0 +1,141 @@
|
||||
//! This module helps us deal with controls and events.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
/// The state of the keyboard.
|
||||
pub struct Keyboard {
|
||||
/// The inner keyboard.
|
||||
inner: Rc<RefCell<InnerKeyboard>>,
|
||||
}
|
||||
|
||||
impl Keyboard {
|
||||
/// Checks wether a key is pressed or not.
|
||||
pub fn is_key_pressed(&self, key: Key) -> bool {
|
||||
let mut b = self.inner.borrow_mut();
|
||||
*b.keys.entry(key).or_insert(false)
|
||||
}
|
||||
|
||||
/// Receives and treats an event.
|
||||
pub fn manage_event(&self, event: Event) {
|
||||
let mut b = self.inner.borrow_mut();
|
||||
match event {
|
||||
Event::KeyPressed(x) => *b.keys.entry(x).or_insert(true) = true,
|
||||
Event::KeyReleased(x) => *b.keys.entry(x).or_insert(false) = false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Keyboard {
|
||||
/// Initializes the keyboard.
|
||||
pub fn new(document: &web_sys::Document) -> Result<Keyboard> {
|
||||
let inner = Rc::new(RefCell::new(InnerKeyboard::new()));
|
||||
|
||||
let clone = Keyboard {
|
||||
inner: inner.clone(),
|
||||
};
|
||||
|
||||
let down_cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::KeyboardEvent| {
|
||||
if let Some(event) = Event::from_js(true, event) {
|
||||
clone.manage_event(event);
|
||||
}
|
||||
});
|
||||
|
||||
document.set_onkeydown(Some(down_cb.as_ref().unchecked_ref()));
|
||||
down_cb.forget();
|
||||
|
||||
let clone = Keyboard {
|
||||
inner: inner.clone(),
|
||||
};
|
||||
|
||||
let up_cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::KeyboardEvent| {
|
||||
if let Some(event) = Event::from_js(false, event) {
|
||||
clone.manage_event(event);
|
||||
}
|
||||
});
|
||||
|
||||
document.set_onkeyup(Some(up_cb.as_ref().unchecked_ref()));
|
||||
up_cb.forget();
|
||||
|
||||
Ok(Keyboard { inner })
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of the keyboard.
|
||||
pub struct InnerKeyboard {
|
||||
/// Holds the state of the keys.
|
||||
keys: HashMap<Key, bool>,
|
||||
|
||||
/// The list of events to be processed.
|
||||
events: Vec<Event>,
|
||||
}
|
||||
|
||||
impl InnerKeyboard {
|
||||
/// Creates a new inner arrowboard.
|
||||
pub fn new() -> InnerKeyboard {
|
||||
InnerKeyboard {
|
||||
keys: HashMap::new(),
|
||||
events: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The different events that can occur.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Event {
|
||||
/// A key was pressed down.
|
||||
KeyPressed(Key),
|
||||
|
||||
/// A key was released.
|
||||
KeyReleased(Key),
|
||||
}
|
||||
|
||||
/// The different key we cant to support.
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum Key {
|
||||
/// The left arrow key.
|
||||
ArrowLeft,
|
||||
|
||||
/// The right arrow key.
|
||||
ArrowRight,
|
||||
|
||||
/// The up arrow key.
|
||||
ArrowUp,
|
||||
|
||||
/// The bottom arrow key.
|
||||
ArrowDown,
|
||||
}
|
||||
|
||||
impl Key {
|
||||
/// Tries and converts a javascript key to our key type.
|
||||
pub fn from_str(string: &str) -> Option<Key> {
|
||||
match string {
|
||||
"ArrowLeft" => Some(Key::ArrowLeft),
|
||||
"ArrowRight" => Some(Key::ArrowRight),
|
||||
"ArrowUp" => Some(Key::ArrowUp),
|
||||
"ArrowDown" => Some(Key::ArrowDown),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Event {
|
||||
/// Tries and converts a javacript event to our event type.
|
||||
pub fn from_js(down: bool, event: web_sys::KeyboardEvent) -> Option<Event> {
|
||||
let key = Key::from_str(&event.code())?;
|
||||
|
||||
let event = if down {
|
||||
Some(Event::KeyPressed(key))
|
||||
} else {
|
||||
Some(Event::KeyReleased(key))
|
||||
};
|
||||
|
||||
event
|
||||
}
|
||||
}
|
77
src/engine/image.rs
Normal file
77
src/engine/image.rs
Normal file
@ -0,0 +1,77 @@
|
||||
//! A module that makes it easier to deal with images.
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
use web_sys::HtmlImageElement;
|
||||
|
||||
use crate::{log, Result};
|
||||
|
||||
/// A wrapper to make it easier to manage HTML images.
|
||||
pub struct Image {
|
||||
/// The inner image.
|
||||
pub inner: Rc<RefCell<InnerImage>>,
|
||||
}
|
||||
|
||||
/// The content of the image.
|
||||
pub struct InnerImage {
|
||||
/// The inner HtmlImageElement.
|
||||
pub inner: HtmlImageElement,
|
||||
|
||||
/// Whether the image has been loaded or not.
|
||||
pub loaded: bool,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
/// Loads a new image from its src.
|
||||
pub fn new(path: &str) -> Result<Image> {
|
||||
let image = HtmlImageElement::new()?;
|
||||
image.set_src(path);
|
||||
|
||||
let image = Image {
|
||||
inner: Rc::new(RefCell::new(InnerImage {
|
||||
inner: image,
|
||||
loaded: false,
|
||||
})),
|
||||
};
|
||||
|
||||
let clone = image.inner.clone();
|
||||
let path_clone = path.to_string();
|
||||
|
||||
let cb = Closure::<dyn FnMut(_)>::new(move |_event: web_sys::Event| {
|
||||
log!("{} loaded", path_clone);
|
||||
(*clone).borrow_mut().loaded = true;
|
||||
});
|
||||
|
||||
image
|
||||
.inner
|
||||
.borrow()
|
||||
.inner
|
||||
.set_onload(Some(cb.as_ref().unchecked_ref()));
|
||||
|
||||
cb.forget();
|
||||
|
||||
Ok(image)
|
||||
}
|
||||
|
||||
/// Returns whether the image is loaded.
|
||||
pub fn is_loaded(&self) -> bool {
|
||||
self.inner.borrow().loaded
|
||||
}
|
||||
|
||||
/// Renders the image on a context.
|
||||
pub fn render(
|
||||
&self,
|
||||
x: f64,
|
||||
y: f64,
|
||||
context: &web_sys::CanvasRenderingContext2d,
|
||||
) -> Result<()> {
|
||||
context.draw_image_with_html_image_element(&self.inner.borrow().inner, x, y)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
196
src/engine/mod.rs
Normal file
196
src/engine/mod.rs
Normal file
@ -0,0 +1,196 @@
|
||||
//! This module contains the whole engine that manages everything.
|
||||
|
||||
pub mod event;
|
||||
pub mod image;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
use crate::engine::event::{Key, Keyboard};
|
||||
use crate::engine::image::Image;
|
||||
use crate::Result;
|
||||
|
||||
/// Our game engine.
|
||||
pub struct Engine {
|
||||
/// The inner engine.
|
||||
///
|
||||
/// We need Rc<RefCell> in order to deal with events.
|
||||
pub inner: Rc<RefCell<InnerEngine>>,
|
||||
|
||||
/// The web page document.
|
||||
pub document: Rc<web_sys::Document>,
|
||||
|
||||
/// The canvas rendering context.
|
||||
///
|
||||
/// We keep a reference so that we can easily render things.
|
||||
pub context: Rc<web_sys::CanvasRenderingContext2d>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
/// Creates a new engine.
|
||||
pub fn new() -> Result<Engine> {
|
||||
let document = web_sys::window().unwrap().document().unwrap();
|
||||
let canvas = document.get_element_by_id("canvas").unwrap();
|
||||
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::<web_sys::HtmlCanvasElement>()?;
|
||||
|
||||
canvas.set_width(1920);
|
||||
canvas.set_height(1080);
|
||||
|
||||
let context = canvas
|
||||
.get_context("2d")?
|
||||
.unwrap()
|
||||
.dyn_into::<web_sys::CanvasRenderingContext2d>()?;
|
||||
|
||||
let inner = InnerEngine::new(&document)?;
|
||||
|
||||
let document = Rc::new(document);
|
||||
let context = Rc::new(context);
|
||||
|
||||
Ok(Engine {
|
||||
inner: Rc::new(RefCell::new(inner)),
|
||||
document,
|
||||
context,
|
||||
})
|
||||
}
|
||||
|
||||
/// Clones the engine.
|
||||
///
|
||||
/// It is made to be efficient, cloning only Rcs.
|
||||
pub fn clone(&self) -> Engine {
|
||||
Engine {
|
||||
inner: self.inner.clone(),
|
||||
document: self.document.clone(),
|
||||
context: self.context.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the engine.
|
||||
pub fn start(&self) -> Result<()> {
|
||||
let clone = self.clone();
|
||||
let cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::Event| {
|
||||
clone.run();
|
||||
});
|
||||
|
||||
web_sys::window()
|
||||
.unwrap()
|
||||
.request_animation_frame(cb.as_ref().unchecked_ref())
|
||||
.unwrap();
|
||||
|
||||
cb.forget();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Launches a loop of the engine, and schedules the next one.
|
||||
pub fn run(&self) -> Result<()> {
|
||||
// Perform update
|
||||
self.update()?;
|
||||
|
||||
// Perform render
|
||||
self.render()?;
|
||||
|
||||
// Schedule next render
|
||||
let clone = self.clone();
|
||||
let cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::Event| {
|
||||
clone.run();
|
||||
});
|
||||
|
||||
web_sys::window()
|
||||
.unwrap()
|
||||
.request_animation_frame(cb.as_ref().unchecked_ref())
|
||||
.unwrap();
|
||||
|
||||
cb.forget();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Triggers the update of the model of the engine.
|
||||
pub fn update(&self) -> Result<()> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
// Perform update
|
||||
let mut dx = 0.0;
|
||||
let mut dy = 0.0;
|
||||
|
||||
if inner.keyboard.is_key_pressed(Key::ArrowDown) {
|
||||
dy += 5.0;
|
||||
}
|
||||
|
||||
if inner.keyboard.is_key_pressed(Key::ArrowUp) {
|
||||
dy -= 5.0;
|
||||
}
|
||||
|
||||
if inner.keyboard.is_key_pressed(Key::ArrowLeft) {
|
||||
dx -= 5.0;
|
||||
}
|
||||
|
||||
if inner.keyboard.is_key_pressed(Key::ArrowRight) {
|
||||
dx += 5.0;
|
||||
}
|
||||
|
||||
inner.x += dx;
|
||||
inner.y += dy;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Performs the rendering of the engine.
|
||||
pub fn render(&self) -> Result<()> {
|
||||
let inner = self.inner.borrow();
|
||||
|
||||
// Perform render
|
||||
self.context.clear_rect(0.0, 0.0, 1920.0, 1080.0);
|
||||
inner
|
||||
.textures
|
||||
.test
|
||||
.render(inner.x, inner.y, &self.context)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The data contained in our engine.
|
||||
pub struct InnerEngine {
|
||||
/// The x position of the drawing.
|
||||
pub x: f64,
|
||||
|
||||
/// The y position of the drawing.
|
||||
pub y: f64,
|
||||
|
||||
/// The keyboard.
|
||||
pub keyboard: Keyboard,
|
||||
|
||||
/// The texture manager.
|
||||
pub textures: TextureManager,
|
||||
}
|
||||
|
||||
impl InnerEngine {
|
||||
/// Initializes the engine.
|
||||
pub fn new(document: &web_sys::Document) -> Result<InnerEngine> {
|
||||
Ok(InnerEngine {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
keyboard: Keyboard::new(document)?,
|
||||
textures: TextureManager::new()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Our texture manager.
|
||||
///
|
||||
/// It holds all our resources.
|
||||
pub struct TextureManager {
|
||||
test: Image,
|
||||
}
|
||||
|
||||
impl TextureManager {
|
||||
/// Creates and start the loading of all our textures.
|
||||
fn new() -> Result<TextureManager> {
|
||||
let test = Image::new("static/image.png")?;
|
||||
Ok(TextureManager { test })
|
||||
}
|
||||
}
|
40
src/lib.rs
Normal file
40
src/lib.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use std::rc::Rc;
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
pub mod engine;
|
||||
|
||||
/// A type that makes dealing with results easier.
|
||||
pub type Result<T> = StdResult<T, JsValue>;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||||
pub fn console_log(s: &str);
|
||||
|
||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||||
pub fn console_log_js(s: JsValue);
|
||||
}
|
||||
|
||||
macro_rules! log {
|
||||
($($t:tt)*) => (crate::console_log(&format_args!($($t)*).to_string()))
|
||||
}
|
||||
|
||||
macro_rules! log_js {
|
||||
($t:tt) => {{
|
||||
let e: JsValue = $t.into();
|
||||
crate::console_log_js(e)
|
||||
}};
|
||||
}
|
||||
|
||||
pub(crate) use log;
|
||||
pub(crate) use log_js;
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn start() -> Result<()> {
|
||||
let mut engine = engine::Engine::new()?;
|
||||
engine.start()?;
|
||||
Ok(())
|
||||
}
|
BIN
static/image.png
Normal file
BIN
static/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 583 KiB |
Loading…
x
Reference in New Issue
Block a user