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パターンの使用は非常に強力ですが、それらのすべてのニュアンスに固執することをあまり気にしないでください。最終的に、アプリケーションが成功したかどうかを決定するのはゲーム体験です:)
検討のため:建築家の宇宙飛行士がジョエル・スポルスキーによってあなたを怖がらせないでください