2048 WASM or play on Rust in 2 days

This article is an experiment with Rust with its subsequent compilation in WASM. It was interesting to feel these technologies on something more difficult than calculating the factorial, so the choice fell on the well-known game 2048 .















Description of the game



The original game is a 4 by 4 square field. Each square can be either empty or occupied by a tile

with a power of two. The starting state of the field has 2 filled cells.















4 : , , ,

. . 90%

10%.







, , :















, , .







, , .







:















, .







: 2048.









Rust, .







Rust.

Yew — , React', ,

.







:







cargo new --lib rust-2048 && cd rust-2048
      
      





, Cargo.toml :







[dependencies]
yew = "0.17"
wasm-bindgen = "0.2.67"
      
      





, src/lib.rs



:







use wasm_bindgen::prelude::*;
use yew::prelude::*;
struct Model {
    link: ComponentLink<Self>,
    value: i64,
}
enum Msg {
    AddOne,
}
impl Component for Model {
    type Message = Msg;
    type Properties = ();
    fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
        Self {
            link,
            value: 0,
        }
    }
    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::AddOne => self.value += 1
        }
        true
    }
    fn change(&mut self, _props: Self::Properties) -> ShouldRender {
        // Should only return "true" if new properties are different to
        // previously received properties.
        // This component has no properties so we will always return "false".
        false
    }
    fn view(&self) -> Html {
        html! {
            <div>
                <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
                <p>{ self.value }</p>
            </div>
        }
    }
}
#[wasm_bindgen(start)]
pub fn run_app() {
    App::<Model>::new().mount_to_body();
}
      
      





:







mkdir static
      
      





index.html :







<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Yew Sample App</title>
    <script type="module">
      import init from "./wasm.js";
      init();
    </script>
  </head>
  <body></body>
</html>
      
      





wasm-pack ( cargo install wasm-pack



):







wasm-pack build --target web --out-name wasm --out-dir ./static
      
      





:







Error: crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your Cargo.toml file:
[lib]
crate-type = ["cdylib", "rlib"]
      
      





, . Cargo.toml :







[lib]
crate-type = ["cdylib", "rlib"]
      
      





( miniserve, ):







cd static
python -m SimpleHTTPServer
      
      





http://127.0.0.1:8000 . , .









: https://github.com/dev-family/wasm-2048/commit/6bc015fbc88c1633f4605944fd920b2780e261c1







.

.







:







2, 4, 0, 0
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





, . :







0, 0, 2, 4
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





, .

:







  1. => .


         /--------  , 
2, 4, 0, 0
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





2.







      /--------  , 
2, 4, 0, 0
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





3.







    /--------   
2, 4, 0, 0
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





4.







       /-------- 
2, 0, 4, 0
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





5.







         /--------   ,        
2, 0, 0, 4
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





6.







 /--------  
2, 0, 0, 4
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





7.







    /-------- 
0, 2, 0, 4
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





8.







       /--------      
0, 0, 2, 4
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
      
      





, , — .







Direction#build_traversal



( ),

Grid#traverse_from



( ) Grid#move_in



— , .









: https://github.com/dev-family/wasm-2048/commit/7e08b5af6008e6f9d716d7c9a41b0810e869df9e







: ,

.. 4 , 2

. , ,

.







, TestCase, .. .









: https://github.com/dev-family/wasm-2048/commit/6082409412f6c19943c453c5d706d57bbcef538b







rand, WASM

wasm-bindgen



feature.







, ,

Grid



enable_new_tiles



.







(.. ),

traverse_from



. , , .







UI



: https://github.com/dev-family/wasm-2048/commit/356e0889a84d7fc2582662e76238f94fc69bfed7







UI , React / JSX. html!



Yew ,

. React - .







There was no documentation on working with the keyboard, and, in principle, the services are not documented in any way, you need to read the sources, watch examples.







Animations



Commit: https://github.com/dev-family/wasm-2048/commit/e258748ab114ec5f930dbeb77d674bdbc5e63b1a .







To make the interface look more lively, you need to add animations.







They are implemented on top of regular CSS transitions. We teach tiles to remember their previous position, and when rendering, we display the tile immediately in the old position, and at the next tick - in the new one.








All Articles