JavaScript MVCアプリケーションの設計(キャンバス)


9

JavascriptのアプローチのようなMVCを使用してキャンバスアプリケーションを構造化/構築する方法を理解するのが困難です。UIはかなり流動的でアニメーション化され、ゲームはかなり単純化されていますが、トゥイーンとアニメーションに重点が置かれています。MVCがどのように機能するかは原則的にわかりますが、実際には機能しません。私はこれからバガリーをグーグルで検索し、ひどいことを読んだので、始めたときと同じように混乱しています。

アプリケーション領域に関するいくつかの詳細:

  • マルチスクリーンゲームフレームワーク-複数のゲームがこのフレームワーク内に配置されます。一般的なUI「スクリーン」には、設定、情報、難易度の選択、メインメニューなどがあります。
  • 複数のインプットメソッド
  • 一部の画面のトップメニューバーなどの一般的なUI要素
  • 異なるレンダリング方法を使用する可能性(キャンバス/ DOM / webGL)

現時点では、AppModel、AppController、AppViewがあります。ここから、各「画面」を追加してAppViewにアタッチすることを計画していました。しかし、トップメニューバーのようなものはどうですか、それらは別のMVCトライアドである必要がありますか?コンポーネントを密結合せずにどこにどのように取り付けますか?

1つのMVCトライアドを別のトライアド内に配置することは受け入れられている慣行ですか?つまり、各「画面」をAppViewに追加できますか?「トライアド」はMVC用語としても受け入れられますか?!

私の心は選択肢の下で溶けています...私はここで基本的な何かを見逃しているように感じます。私はMVCアプローチを使用せずにすでに稼働しているソリューションを持っていますが、結局、密結合されたスープ-ロジックとビューを組み合わせて、現在組み合わせています。アイデアは、それを開いて、ビューを簡単に変更できるようにすることでした(たとえば、キャンバスビューをDOMベースのビューと交換するため)。

現在使用されているライブラリ:require.js、createJS、アンダースコア、GSAP、手動のMVC実装

特に物事の実際のデザイン、および「スクリーン」を適切なM、V、またはCに分割することに関して、ポインタ、例などをいただければ幸いです。

...またはMVC以外のより適切な方法

[NB、他に2つの誤ったstackexchangeコミュニティで質問したことがある前にこの質問を見た場合...私の脳が機能しなくなった]


1
最終的に適切なサイトを見つけたようです。Gamedevはあなたの質問を望んでいませんか?
ロバートハーベイ

@RobertHarveyは、ここの方が関連性が高いと考えました...少なくともそう願っています!
wigglyworm

回答:


3

MVCは非常に多くの場所で取り上げられているため、ここで繰り返し説明することはあまりありません。基本的に、オブジェクトグラフ、ヘルパー、ロジックをモデル層に含める必要があります。ビューは、ページの動的な部分を満たすために押し出される画面になります(そして、少量のロジックとヘルパーが含まれる場合があります)。また、コントローラーは、オブジェクトグラフ、ヘルパー、およびロジックから得られたものに基づいて画面を提供するための軽量な実装です。

型番

これは、アプリケーションの中心となる場所です。サービス層、ロジック層、エンティティ層に階層化できます。これはあなたの例にとって何を意味しますか?

エンティティレイヤー

これには、ゲームのモデルと内部動作の定義が含まれているはずです。たとえば、マインスイーパ用のゲームがある場合、これは、ボードと四角形の定義と、それらが内部状態をどのように変更するかということになります。

function Location(x,y){
 this.x = x;
 this.y = y;
}
function MineTile(x,y){
 this.flagged = false;
 this.hasMine = false;
 this.pristine = true;
 this.location = new Location(x,y);
}
MineTile.prototype.expose = function(){
 if( this.hasMine ) return false;
 this.pristine = false;
 return this.location;
};

MineTileは、その内部状態を知ることができますので、それが表示されているか(検討した場合などthis.pristine、それは私を(持っているタイルの1つだった場合、) this.hasMineしかし、それは私のものを持っていることになっていたかどうかを判断しません。それはロジック層までです。(さらにOOPに進むために、MineTileは汎用タイルから継承できます)。

ロジック層

これは、アプリケーションがモードの変更や状態の維持などと対話する複雑な方法を収容する必要があります。したがって、現在のゲームの状態を維持するために、メディエーターパターンが実装されるのはここです。これは、たとえばゲームオーバー中に何が起こるかを決定するため、またはどのMineTilesが鉱山を持つかを設定するためのゲームロジックが存在する場所です。エンティティレイヤーを呼び出して、論理的に決定されたパラメーターに基づいてインスタンス化されたレベルを取得します。

var MineSweeperLogic = {
 construct: function(x,y,difficulty){
  var mineSet = [];
  var bombs = 7;
  if( difficulty === "expert" ) bombs = 15;
  for( var i = 0; i < x; i++ ){
   for( var j = 0; i j < y; j++ ){
    var mineTile = new MineTile(i,j);
    mineTile.hasMine = bombs-- > 0;
    mineSet.push(mineTile);
   }
  }
  return mineSet;
 },
 mineAt: function(x,y,mineSet){
  for( var i = 0; i < mineSet.length; i++ )
   if( mineSet[i].x === x && mineSet[i].y === y ) return mineSet[i];
 }
};

サービス層

これは、コントローラがアクセスできる場所です。ゲームを構築するためのロジックレイヤーにアクセスできます。完全にインスタンス化されたゲームまたは変更されたゲームの状態を取得するために、サービス層に高レベルの呼び出しを行うことができます。

function MineSweeper(x,y,difficulty){
 this.x = x;
 thix.y = y;
 this.difficulty = difficulty;
 this.mineSet = MineSweeperLogic.construct(x,y,difficulty);
}
MineSweeper.prototype.expose = function(x,y){
 return MineSweeperLogic.mineAt(x,y,this.mineSet).expose();
}

コントローラ

コントローラは軽量である必要があります。基本的に、これはクライアントとしてモデルに公開されるものです。多くのコントローラーがあるので、それらを構造化することが重要になります。コントローラ関数の呼び出しは、JavaScriptイベントがUIイベントに基づいてヒットするものになります。これらは、サービスレイヤーで利用可能な動作を公開し、クライアントのビューを設定または変更する必要があります。

function MineSweeperController(ctx){
 var this.context = ctx;
}
MineSweeperController.prototype.Start = function(x,y,difficulty){
 this.game = new MineSweeper(x,y,difficulty);
 this.view = new MineSweeperGameView(this.context,this.game.x,this.game.y,this.game.mineSet);
 this.view.Update();
};
MineSweeperController.prototype.Select = function(x,y){
 var result = this.game.expose(x,y);
 if( result === false ) this.GameOver();
 this.view.Select(result);
};
MineSweeperController.prototype.GameOver = function(){
 this.view.Summary(this.game.FinalScore());
};

見る

ビューは、コントローラーの動作に関連して整理する必要があります。キャンバスを扱うため、アプリケーションの中で最も集中的な部分になるでしょう。

function MineSweeperGameView(ctx,x,y,mineSet){
 this.x = x;
 this.y = y;
 this.mineSet = mineSet;
 this.context = ctx;
}
MineSweeperGameView.prototype.Update = function(){
 //todo: heavy canvas modification
 for(var mine in this.mineSet){}
 this.context.fill();
}

これで、この1つのゲームのMVCセットアップ全体ができました。あるいは、少なくとも、最低限必要な例として、ゲーム全体を書き出すことは過剰でした。

これがすべて完了したら、アプリケーションのグローバルスコープがどこかにある必要があります。これは、このシナリオのすべてのMVCスタックへのゲートウェイである現在のコントローラーの寿命を保持します。

var currentGame;
var context = document.getElementById("masterCanvas").getContext('2d');
startMineSweeper.click = function(){
 currentGame = new MineSweeperController(context);
 currentGame.Start(25,25,"expert");
};

MVCパターンの使用は非常に強力ですが、それらのすべてのニュアンスに固執することをあまり気にしないでください。最終的に、アプリケーションが成功したかどうかを決定するのはゲーム体験です:)

検討のため:建築家の宇宙飛行士がジョエル・スポルスキーによってあなたを怖がらせないでください


@TravisJに感謝-ゲームに関連するMVCの素晴らしい説明として賛成。まだはっきりしない点もあると思いますが、あなたが言うように、私はパターンのニュアンスに行き詰まってしまい、前進するのを止めています。コントローラでthis.view.Select()を使用したことが1つありました。このタイプの密結合が必要ですか、それともさらに分離する方法がありますか?
ウィグリムワーム2014年

@wigglyworm-デカップリングが常に存在する可能性があります!:Dしかし、実際には、コントローラーはモデルと通信してビューを更新するコントローラーである必要があります。そのため、MVCでほとんどの結合が行われます。
Travis J

2

これは、すでに間違っていることです。混乱した状態で、MVCが手元にないときにMVCを手動でローリングしました。

PureMVCを見てください。これは言語に依存しないため、実際にMVCを実行することに慣れるのに最適なプラットフォームです。

そのコードは小さくてわかりやすいので、これを使用することで、必要に応じてコードを微調整できます。

それを使って小さなシンプルなゲームを書き始めましょう。マインスイーパがいいでしょう。Travis Jの発言の多くは、特にモデルに関しては良いことです。コントローラー(少なくともPureMvcでは)はステートレスであり、存在し、簡単な作業を行って消えることを覚えておく必要があることだけを付け加えておきます。彼らは知識のある人です。それらは関数のようなものです。「グリッドを塗りつぶし、モデルを変更しました」、「モデルを更新し、ボタンを押しました」

ビュー(PureMVCのメディエーター)は最も馬鹿げており、モデルは少しだけスマートです。どちらも実装を抽象化するため、ユーザー(コントローラー)が直接UIやDBに触れることはありません。

UIのすべての要素(たとえば、winformsアプリなど)にはビュー(メディエーター-なぜこれがより優れた用語であるのかがわかりますか?)がありますが、メディエーターは "Control Color"や "Focus UI要素全体で動作するマネージャー」。ここで重ねて考えます。

UIおよびDBイベントは自動的にコントローラーを呼び出すことができ(スマート命名スキームを使用している場合)、特定のコントローラーを段階的に廃止できます。メディエーターは、モデルデータ変更イベントを直接リッスンし、そのデータパッケージを配信できます。

これは一種のごまかしであり、モデルはそこに何があるかについて少し知っている必要があり、メディエーターはデータパッケージで何をすべきかを理解する必要がありますが、多くの場合、ありふれたコントローラーに煩わされることはありません。

モデル:ばかだが再利用可能。コントローラー:スマートですが再利用性は低くなります(アプリです)。メディエーター:ばかだが再利用可能。この場合の再利用性とは、別のアプリへの移植性を意味します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.