キャンバスなしでゲームを作成する:Matreshka.js

すべてのhabretchitelに良い!



前の記事で、 HeartStoneのように、キャンバスを使用せずにDOM操作を使用してカードゲームを作成する方法を検討しました。



今日は、この場合に最も役立つMatreshka.jsライブラリをこのケースに接続して、このトピックを続けます。

画像



はじめに





前回来たことを簡単に思い出してください。 サーバーとの通信はWebSocketsを介して実行され、次の形式のJSONオブジェクトを渡します:{"method":method、 "args":arguments}。

サーバー側はphpを使用して実装され、スクリプトはデーモン(無限ループ)としてヌルストリームに起動されました。

クライアントは同じタイプのJSON文字列を受け入れ、Actionsオブジェクトのメソッドを呼び出します(前の記事で詳しく説明します)。



socket.onmessage
socket.onmessage = function (e){ if (typeof e.data === "string"){ var request = JSON.parse(e.data); console.log('Response: ' + request.function); Actions[request.function](request.args); }; }
      
      









入れ子人形を紹介し始めます



入れ子人形を実装できる最初の場所は、プレーヤーのリストを含むメニューです。 私の意見では、一般的に、マトリョーシカのリストは非常に便利です。



そのため、タスク:JSONプレーヤーのリストを取得し、接続するときにそれらを描画してイベントを割り当てる必要があります。

デザインは気にしません。



入れ子人形のリストは、モデルとクラス(まあ、クラスのオブジェクト)で構成されます。

私たちの場合

リストモデル
 var listModel = Matreshka.Class({ //   'extends': Matreshka.Object, //   Matreshka.Object  constructor: function(data){ this.jset(data); this.on('render',function(){ //     this.bindNode('name',':sandbox .name',Matreshka.binders.innerHTML()); //    this.bindNode('letsFight',':sandbox .fightButton'); //      this.on('click::letsFight',function(){ Actions.figthRequest(this.name); }); }); } });
      
      









ここで何が起こったのか見てみましょう。「プレイヤーのバインド」とはどういう意味ですか?

入れ子人形のデザイン

 this.bindNode('name',':sandbox .name',Matreshka.binders.innerHTML());
      
      





これは、nameプロパティをバインドすることを意味します。このプロパティは、オブジェクト(Obj.name)のプロパティとして使用できます。この場合は、セレクタ ':sandbox .name'のエンティティです。sandboxはサンドボックス、つまり、ちょうどレンダリングされました。 これは特定のリストアイテムのレンダリングイベントであることを思い出させてください。

依存関係のタイプを3番目の引数として渡します。 つまり、それら(プロパティとエッセンス)の相互接続方法です。

Matryoshkaにはバインダーの標準セットがあり、この場合、Matreshka.binders.innerHTML()は、プロパティの値とhtmlコンテナーのコンテンツを「:sandbox .name」に依存させます。

それらの間の正確な関係は何ですか? 最も明白なのは、オブジェクトのプロパティを変更することです。htmlコンテナのコンテンツが変更されます。



モデルの基本は分解され、クラスに進みます

 var listArray = Matreshka.Class({ //   'extends': Matreshka.Array, Model: listModel, //   itemRenderer: '<li class="player"><span class="name"></span><span class="fightButton"></span></li>', //     constructor: function(){ this.bindNode('sandbox','#players'); //    } });
      
      







教室では、非常に単純なものではありますが、2つのことに集中する価値があります。 itemRendererプロパティは、リスト内の各アイテムがどのように描画されるかを示します。 上記の例では、>>はサンドボックスで、そこから他のセレクターをカウントします。



ご注意

  constructor: function(){ this.bindNode('sandbox','#players'); //    }
      
      





リストのすべての要素がコンテナ「#players」内に描画されると述べています。



バトルモードのマトリョーシカ



プレイヤーが接続してゲームを開始したとき、私たちには何がありますか(論理的に):





これらのリストを入れ子人形の助けを借りて実装し、いくつかのイベントを依頼することは残っています。



私の手にあるカード



私の手にあるカード
 var myCardsModel = Matreshka.Class({ //   'extends': Matreshka.Object, constructor: function(data){ this.jset(data); this.on('render',function(){ this.bindNode('name',':sandbox .title',Matreshka.binders.innerHTML()); this.bindNode('attack',':sandbox .attack .value',Matreshka.binders.innerHTML()); this.bindNode('health',':sandbox .health .value',Matreshka.binders.innerHTML()); this.bindNode('mana',':sandbox .mana .value',Matreshka.binders.innerHTML()); this.bindNode('picture',':sandbox .picture',{ setValue: function(v){ this.innerHTML = '<img src="img/' + v + '">' } }); this.on('click::sandbox',function(){ myArenaCards.push(this); myCards.splice(myCards.indexOf(this),1); Actions.send('putCard',this.toJSON()); }); }); } }); var myCardsArray = Matreshka.Class({ //   'extends': Matreshka.Array, Model: myCardsModel, itemRenderer: '<div class="card">' +'<div class="title"></div>' +'<div class="health"><div class="svg">' + $b('#icons #heart')[0].innerHTML + '</div><div class="value"></div></div>' +'<div class="attack"><div class="svg">' + $b('#icons #attack')[0].innerHTML + '</div><div class="value"></div></div>' +'<div class="mana"><div class="svg">' + $b('#icons #diamond')[0].innerHTML + '</div><div class="value"></div></div>' +'<div class="picture"></div>' +'</div>', constructor: function(){ this.bindNode('sandbox','#myhand'); //    } }); var myCards = new myCardsArray; //   
      
      









同様のリストは繰り返さず、ここでバインドがどのように適用されるかを検討します。

  this.bindNode('name',':sandbox .title',Matreshka.binders.innerHTML()); this.bindNode('attack',':sandbox .attack .value',Matreshka.binders.innerHTML()); this.bindNode('health',':sandbox .health .value',Matreshka.binders.innerHTML()); this.bindNode('mana',':sandbox .mana .value',Matreshka.binders.innerHTML());
      
      







上で説明したように、これらの行はhtmlノードのコンテンツとオブジェクトのプロパティをバインドします。

上記の方法でそれらを接続することにより、リストにプッシュするだけで簡単にマップを作成できます。

 var Actions = { ......... cardToHand: function(card){ myCards.push({ name: card.name, attack: card.attack, health: card.health, picture: card.picture, mana: card.mana }); } ......... }
      
      







とても簡単です。 しかし、これらのプロパティを変更する方法はさらに簡単です。

 this.health = 0;
      
      





ヘルスインジケータをゼロに設定するだけでなく、目的のオブジェクトにHTMLでレンダリングします。

しかし、これだけではありません。健康の変化も追跡する必要があり、1未満になった場合はユニットの死を開始します。 これを行うには、オブジェクトのhealthプロパティをマップ自体に関連付けます。

  this.bindNode('health',':sandbox',{ setValue: function(v){ if (v < 1){ this.className += ' die'; var iot = myArenaCards.indexOf(this); setTimeout(function(){ myArenaCards.splice(iot,1); },2000); }; } });
      
      





3番目の引数は、私が言ったように、通信のロジックを設定します。 この例では、ロジックは次のとおりです。

オブジェクトのヘルス値が変更(設定)されたら、関数を実行します

  function(v){ if (v < 1){ this.className += ' die'; var iot = myArenaCards.indexOf(this); setTimeout(function(){ myArenaCards.splice(iot,1); },2000); }; }
      
      





これは、マップ全体、サンドボックス(2番目の引数: ':sandbox')を指します。



おわりに



双方向および複数のバインディングが本当に必要な複雑なアプリケーションでは、入れ子人形は開発をより簡単にし、快適さを生み出します。

結局のところ、あなたは好きなようにバインドすることができます。ある場合には、受け入れられた値(setValue)のみに処理を行い、別の場合には、イベントによるプロパティの変更(on: 'click'、getValue:function(){})を行います。






All Articles