7 ms·
Rocket – A Rust game running on WASM
- Tade0 9y agoNice! I was worried that there would always be a lot of tweaking necessary to make things compile for this target but apparently that's not the case.
- wofo 9y agoIt was surprisingly easy after I figure out some basic WASM stuff!
- blixt 9y agoCool! One question – you are moving a lot in and out of the JavaScript and Rust "worlds" in your render function. Have you measured the difference of just creating a simple data structure with the render instructions and passing that once to JavaScript instead? I would expect that to be much faster.
- wofo 9y agoI haven't measured anything :P Regarding your suggestion, I cannot pass an object to Javascript, because from the perspective of the browser I am writing C. An alternative would be to have each function take a pointer to the object, but it is quite cumbersome and I doubt it would have any (positive) impact on performance.
- kayoone 9y agoso you can only pass simple types and nothing like a framebuffer array ? great work btw!
- wofo 9y agoSince WASM in its current state is meant as a compilation target for C, it is usually possible to do things "the C way". For instance, you can allocate a buffer on the Javascript side and pass a pointer to the Rust side, which then can write to it. You can also allocate it on the Rust side and return it. This is for instance what you do when you want to return a string.
- blixt 9y agoI was thinking you can create a byte buffer of fixed size instructions that you can pass from Rust to JavaScript. With for example DataView you can fairly easily inspect that data in JavaScript. Or to keep things even simpler, if every class of draw instructions is always performed in order (so not drawEnemy, drawText, then another drawEnemy) you could just have separate arrays of arguments for every draw type. Anyway for your game specifically I doubt this is even close to an issue, but I'm curious just how performance scales when you jump in and out of JS a lot in WASM.
- wofo 9y agoNever heard of DataView before, thanks! This is the first time I do something "low level" in Javascript, so there is probably a lot that could be improved. BTW, here is an example passing arrays between Javascript and Rust: https://www.hellorust.com/demos/canvas/index.html https://www.hellorust.com/demos/canvas/index.html
- Game_Ender 9y agoThe interface between WASM and JS is limited to native types that WASM supports which is just integers [0] (and maybe doubles?). With that limited API you cannot pass full structures around, the best you can do is pass what are essentially pointers to memory around [1]. [0] - https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#Signatures_and_parameters https://developer.mozilla.org/en-US/docs/WebAssembly/Underst... [1] - https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97 https://becominghuman.ai/passing-and-returning-webassembly-a...
- wofo 9y agoDoubles are supported as well through the `f64` type I think. Interestingly, I am passing booleans in my code as well... and it seems to work.
- landonxjames 9y agoI wonder if its converting them to 0's and 1's and sending that to the javascript?
- wofo 9y agoJust checked what is going on and that is indeed the case. Rust booleans compile now to the i32 type (though there is no guarantee that will stay like that in the future).
- onion2k 9y agoYou can do something very similar in plain JS using a sharedArrayBuffer and a webworker. A sharedArrayBuffer is a typed array in an area of shared memory that the worker and the main script can both access. It works really well if it fits your use case. I wrote a 'javascript snow' thing that uses it - https://github.com/onion2k/snowfall https://github.com/onion2k/snowfall
- Aissen 9y agoI'd love if those to see those web games start to use KeyboardEvent.code https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve... ; which is much more portable across keymaps and layouts than "key". Unfortunately, it's hindered by slow Edge & Android adoption: https://caniuse.com/#feat=keyboardevent-code https://caniuse.com/#feat=keyboardevent-code
- mrec 9y agoI hadn't seen KeyboardEvent.code before, but after a quick skim I can't see how you'd use it in practice. Being able to recognize physical key positions is nice and all, but how do you map those to the character printed on the key so that you can tell the user what the controls are, before the user has pressed them? The demo in that MDN page has the help text "Use the WASD (ZQSD on AZERTY) keys to move and steer" which doesn't inspire much confidence if it implies that you need to list controls for every possible keyboard layout and rely on the user knowing what they've got.
- htgb 9y agoI'm not sure if it's possible to access the character given the key code (the docs you linked implies it's not), but when we're interested in physical keys, I'd much rather use that nonetheless. A good way to illustrate the controls could maybe be with an image? The keys on the image could say WASD for all I care, as long as I'm able to see the position of them, which is what matters. There are similar issues for other things than games. Quite a few programs have `Ctrl + /` or similar as a keyboard shortcut, which is easy on an american keyboard, but on a Swedish one there's no dedicated key for slash (it's `Shift + 7`). The same goes for most symbols except A-Z (I use Swedish QWERTY), they are in other locations and with other modifiers. Best, of course, is when you can get the character based on the physical key. One example of this is Visual Studio Code, where the shortcut for toggling the console is `Ctrl + Ö`, and presented as such. I assume they defined the shortcut by the physical key (the one to the right of `L` in this case) and presented it by its character.
- 9y ago
- jerianasmith 9y agoSlow Edge & Android adoption are a major hindrance. The time needed to figure out integration between JavaScript and Rust is too long.
- executesorder66 9y agoWhy does Edge adoption matter? The highest browser usage share I could find for Edge was 4.21%
- hood_syntax 9y ago4% is still a decent portion of the market, and likely contains a more desirable market demographic than those that are on IE (depending on your product, obviously). I'm not saying it's really important, but any potential users gained is a good thing, right?
- nullifidian 9y agoI don't understand how it's a problem. Just show a message "Your browser is not supported. Please use one of the following browsers." To play games on Windows people install MANY proprietary launchers(From Blizzard, EA, UBI, etc. Steam is a glorified launcher also), I don't see how installing Chrome just to play a game is more difficult.
- hood_syntax 9y agoI'm with you on that, and it's the reason at my job we aren't bending over backwards for compatibility. We don't support IE. It's not _really_ a problem, but it could lose you users. How many, I don't know. Whether that's a problem or not is up to you.
- hinkley 9y agoTurn the question around: can we do something else with those resources to get 4% more users and an increase in goodwill?
- maffydub 9y agoNice one, and thanks for the write-up! I spent the weekend playing around with Rust/WebAssembly too - calling between Rust and WebAssembly is a bit more fiddly than I expected, but I can understand why they did it. I ended up trying to write a text adventure in Rust/WebAssembly for Ludum Dare (https://ldjam.com/events/ludum-dare/40 https://ldjam.com/events/ludum-dare/40). Due to other commitments, I ran out of time for the (48-hour) "competition", but am hoping to get something working in time for the (72-hour) "jam", which ends tonight. (Brief blog on my initial experiences at https://maffydub.wordpress.com/2017/12/02/getting-started-with-rust-webassembly/ https://maffydub.wordpress.com/2017/12/02/getting-started-wi... .)
- wofo 9y agoAwesome! Happy to see the WASM backend is getting more and more attention
- frik 9y agoIt sucks, there is no way to view the code in Chrome DevTools. The WASM file isn't listed in DevTools "source" tab at all. https://aochagavia.github.io/js/rocket.wasm https://aochagavia.github.io/js/rocket.wasm A binary blob, that cannot be viewed except with an offline hexeditor. WASM sucks. Please remove support and go back to ASM.js, at least it was readable and fast. Or transpile to JS in the first place. Thanks for destroying the open web.
- maffydub 9y agoIt's listed in Chrome for me. If I go to https://www.hellorust.com/demos/add/index.html https://www.hellorust.com/demos/add/index.html, bring up the "Sources tab under Chrome Developer Tools and click on "Run", then a "wasm" item appears - clicking on that shows me the disassembly. Do you not see a "wasm" item? While WebAssembly clearly isn't as readable as non-minified JavaScript, it's probably not much worse than minified Javascript, and I really can't see any difference from a readability perspective between this and ASM.js.
- diggan 9y ago
- junke 9y agoVery good. As for the game itself, the fact that the yellow asteroids can appear right in front of the ship is frustrating (death by bad luck: the player can't do anything to avoid it).
- gpm 9y agoAnd apart from that holding space + arrow is a very effective strat, doubly so if you do it so half your circle wraps from one end to the other confusing the tracking. Maybe shooting needs a cost associated with it.
- ezekg 9y agoI got that "perfect circle" hitting all 4 corners and really started messing with the pathfinding--it started pulling all of the enemies into the center until a baddie spawned on me and ended my streak. Fun game, and really interesting article on WASM.
- v512 9y agoAlso if you are able to circle between top-bottom or left-right then the balls get confused and change their direction constantly so easy to kill.
- deleted 9y ago[deleted]
- wofo 9y agoI didn't expect people to comment on the game itself... It is indeed quite simple at the moment. Maybe your opportunity to get your feet wet with Rust by improving the game logic?
- makmanalp 9y agoI'm currently sick at home and I don't have the mental energy to do anything useful but I actually found this oddly amusing and mesmerizing ... Because you shoot so quickly and turn so fast, I found that you can just hold down the spacebar and turn around to use your stream of projectiles kinda like a whip, turning left and right to get the curvy stream to intersect with the ships. This also defeats most of the right-in-front-of-you spawns. Anyway, very neat!
- mring33621 9y agowow -- starts and runs very smoothly! A very good POC!
- krylon 9y agoI have to admit I was surprised how smoothly this runs, even on a relatively low-power CPU (Core m3).
- zengid 9y agoExcellent write up! Thank you for taking the time: I've been uncertain how people manage to get the JS to interop with <Compile-to-WASM-lang>.
- haberman 9y agoLooks like the actual artifacts are a 6kB html (with embedded JS) and a 52kB .wasm file. https://github.com/aochagavia/rocket_wasm/tree/master/html https://github.com/aochagavia/rocket_wasm/tree/master/html It's very nice to see that this "scales down", so-to-speak. It can be really disheartening to see small programs compile into hundreds-of-kB binary images. It's great to see that Rust+WASM can be so lean!
- steveklabnik 9y agoa "add one to a number and return it" compiled this way results in a ~100 byte binary. It's about twice the size of writing it by hand, but those gains get lost as soon as you start doing real things, so it's not a big deal. One big jump in binary size starts when you use the allocator, as then it needs to include the allocator's code.
- haberman 9y agoIt would be nice if there was a modern malloc implementation (with good multi-threaded performance) that optimized for size.
- steveklabnik 9y agoWe use a Rust port of dlmalloc with this toolchain. Multithreading doesn't matter to wasm yet, incidentally; it's still single threaded.
- wofo 9y agoNote that I am using the allocator in Rocket, so I would estimate the size to be something around 40kB
- Karrot_Kream 9y agoSlightly off-topic. Does WASM support function pointers yet?
- fasquoika 9y agoI think so. See `call_indirect` here: https://github.com/WebAssembly/design/blob/master/Semantics.md#table https://github.com/WebAssembly/design/blob/master/Semantics....
- exabrial 9y agoInteresting to see WASM targets for languages popping up. My personal favorite is this one for JVM->WASM: http://teavm.org/ http://teavm.org/
- cproctor 9y agoFinally, I broke 500! If you get your ship circling so that it appears briefly in each corner, you can get a nice stationary cloud of dots.
- dm319 9y agoThis game needs a highscore...
- sebringj 9y agojust periodically hold down left and space to get lots of points awesome future ahead for games!
- King-Aaron 9y agoYou might want to look up the colloquial meaning behind "red rocket" before using it in branding exercises... :P