2048


この記事は、WASMでのその後のコンパイルで錆の実験です.
これらの技術をファクターを計算するよりも難しいものにしようとするのはおもしろかった.

ゲーム


元のゲームは4スクエアフィールド4を表します.それぞれの正方形のいずれかを空にすることができますまたは2タイルの数でタイルによって占められている.フィールドの開始状態は2つの塗りつぶしセルを持つ.

プレイヤーは4方向のいずれかで移動することができます:右、上、下、すべてのタイルを選択した方向にすべての方法を移動します.新しいタイルは、各移動後に表示されます.新しいタイルは、90 %の確率または4で2を含みます
10 %の確率で.
たとえば、上記の開始状態から右側に移動しましょう.

番目の行のタイルは右の境界線に対して休まれ、2は最初の行、3列目に現れた.
タイルが同じ数を含む別のタイルにかかっている場合、それらは2の次のパワーの1つのタイルにマージされます.
前の状態から動きましょう

1行目と2行目の最後の列のtwosが1つにマージされ、さらに4行目が4行目に現れました.
ゲームの目的:番号2048でタイルに到達.

準備


私のためにこの実験のゴールの1つがさびで遊ぶことになっていたので、言語を選ぶ仕事はありません.
This pageは、さびのためのフロントエンドフレームワークのリストを提供します.
最も人気のあるオプション- Yew -面白い場合、特に反応した経験があります.
プロジェクトの作成手順はhere :
cargo new --lib rust-2048 && cd rust-2048
次に、貨物に依存性を追加します.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
内部でインデックスを作成します.以下の内容を持つ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パックを使用してプロジェクトをビルドします.
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"]
わかりましたので、しましょう.オープンカーゴ.最後にtomlとadd :
[lib]
crate-type = ["cdylib", "rlib"]
ここで、静的サーバを起動して結果をチェックすることができます(例ではminiserveをインストールすることを提案しますが、標準的なPythonモジュールを使用します).
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
選択した方向の最後から移動し、選択した方向にすべてのタイルを移動する場合は、この行動を達成することができます.
私はより良い理解のために手動で繰り返します
  • 選択された方向は右=.
  •          /-------- empty cell, skip
    2, 4, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    2 .
          /-------- empty cell, skip
    2, 4, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    3 .
        /-------- start to shift to the right
    2, 4, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    4 .
           /-------- continue
    2, 0, 4, 0
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    5 .
             /-------- reached the end, return to the next position from which we began to move
    2, 0, 0, 4
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    6 .
     /-------- move to the right
    2, 0, 0, 4
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    7.
        /-------- continue
    0, 2, 0, 4
    0, 0, 0, 0
    0, 0, 0, 0
    0, 0, 0, 0
    
    8 .
           /-------- stop and go to the next line
    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
    タイルを組み合わせて1つのニュアンス:タイルは、4つの同一のタイルを重複した場合は、次の力の2タイルになります一度以上マージしないでください.したがって、タイルは、各移動する前にドロップする必要がある特定の状態を持つ必要があります.
    また、TestCaseの構造を変更しなければなりませんでした
    つの動き.

    新しいタイルの追加


    コミット:https://github.com/dev-family/wasm-2048/commit/6082409412f6c19943c453c5d706d57bbcef538b
    rand packageはランダムに使用されます.また、それはwasm-bindgen機能を加えることによってWASM環境で働きます.
    新しいタイルの準備ができていない前のテストを中断しないために、enable_new_tilesの構造に新しいフラグフィールドGridを追加しました.
    新しいタイルは有効な移動(すなわち、移動中に発生した少なくとも1つのフィールド変更)の場合にのみ追加する必要があるため、traverse_fromシグネチャが変更されます.このメソッドは、動きがあるかどうかを示すブール値を返します.

    UI


    コミット:https://github.com/dev-family/wasm-2048/commit/356e0889a84d7fc2582662e76238f94fc69bfed7
    UIの部分は、特にそれらの反応および/またはJSXに精通して実装するために、非常に簡単です.YaW hereからhtml!マクロについて読むことができます.
    そして、一般的にhereのコンポーネントについて.それは私にprehook回で多くの反応を思い出させる.
    キーボードで動作する文書はありませんでした、そして、原則として、サービスはどんな方法ででも文書化されません、したがって、あなたは源を読む必要があります、例を見てください.

    アニメーション


    コミットします.
    インターフェイスをより活発に見えるようにするには、アニメーションを追加する必要があります.
    それらは通常のCSS遷移の上に実装されます.我々は、古い位置にすぐにタイルを表示するレンダリング中に前の位置を覚えてタイルを作り、次のティック-新しいもので.