Desain aplikasi Javascript MVC (kanvas)


9

Saya mengalami kesulitan memahami bagaimana struktur / arsitek aplikasi kanvas menggunakan pendekatan seperti MVC di Javascript. UI akan cukup lancar dan beranimasi, gim-gim ini cukup sederhana namun dengan penekanan besar pada tweening dan animasi. Saya mengerti bagaimana MVC bekerja pada prinsipnya tetapi tidak dalam praktiknya. Saya sudah mencari Google buggery ini, banyak membaca, dan sekarang saya sama bingungnya dengan ketika saya mulai.

Beberapa detail tentang area aplikasi:

  • kerangka kerja multi layar - beberapa game akan berada dalam kerangka ini "layar" UI umum meliputi: pengaturan, info, pilih kesulitan, menu utama dll.
  • beberapa metode input
  • elemen UI umum seperti bilah menu atas di beberapa layar
  • kemungkinan menggunakan metode rendering yang berbeda (canvas / DOM / webGL)

Saat ini saya memiliki AppModel, AppController, dan AppView. Dari sini saya berencana untuk menambahkan masing-masing "layar" dan melampirkannya ke AppView. Tapi bagaimana dengan hal-hal seperti bilah menu atas, haruskah mereka menjadi triad MVC lain? Di mana dan bagaimana saya akan memasangnya tanpa komponen kopling erat?

Apakah itu praktik yang diterima untuk memiliki satu triad MVC di dalam yang lain? yaitu, bisakah saya menambahkan setiap "layar" ke AppView? Apakah "triad" bahkan merupakan istilah MVC yang diterima ?!

Pikiranku meleleh di bawah pilihan ... Aku merasa seperti kehilangan sesuatu yang mendasar di sini. Saya punya solusi yang sudah berjalan dan berjalan tanpa menggunakan pendekatan MVC, tetapi telah berakhir dengan sup - logika dan pandangan yang sangat erat dan saat ini digabungkan. Idenya adalah untuk membukanya dan memungkinkan perubahan tampilan yang lebih mudah (misalnya mengubah tampilan kanvas dengan tampilan berbasis DOM).

Pustaka saat ini digunakan: require.js, createJS, garis bawah, GSAP, implementasi MVC linting tangan

Setiap petunjuk, contoh, dll., Khususnya yang berkaitan dengan desain benda yang sebenarnya dan memisahkan "layar" menjadi M, V, atau C yang tepat akan dihargai.

... atau metode yang lebih tepat selain MVC

[NB, jika Anda pernah melihat pertanyaan ini sebelumnya karena saya bertanya di 2 komunitas stackexchange yang salah lainnya ... otak saya telah berhenti berfungsi]


1
Sepertinya Anda akhirnya menemukan situs yang tepat. Gamedev tidak menginginkan pertanyaan Anda?
Robert Harvey

@RobertHarvey berpikir itu mungkin lebih relevan di sini ... setidaknya saya harap begitu!
cacing gelang

Jawaban:


3

MVC telah dibahas di banyak tempat sehingga tidak ada banyak yang harus diulang lagi di sini. Pada dasarnya Anda ingin grafik objek, helper, dan logika Anda terkandung dalam tier model. Tampilan akan menjadi layar yang terdorong keluar untuk mengisi bagian dinamis halaman (dan mungkin mengandung sedikit logika dan bantuan). Dan controller, yang menjadi implementasi ringan untuk melayani layar berdasarkan apa yang tersedia dari objek grafik, helper, dan logika.

Model

Ini harus berada di tempat daging aplikasi duduk. Itu dapat dibagi menjadi lapisan layanan, lapisan logika, dan lapisan entitas. Apa artinya ini untuk contoh Anda?

Lapisan entitas

Ini harus menampung definisi model dan perilaku internal gim Anda. Misalnya, jika Anda memiliki permainan untuk kapal penyapu ranjau, ini akan menjadi tempat definisi papan dan kuadrat bersama dengan bagaimana mereka mengubah keadaan internal mereka.

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;
};

Jadi MineTile akan mengetahui keadaan internalnya, seperti apakah itu menunjukkan atau diperiksa ( this.pristine), apakah itu salah satu ubin yang memiliki tambang ( this.hasMine) tetapi tidak akan menentukan apakah itu seharusnya memiliki tambang. Itu akan sampai ke lapisan logika. (Untuk melangkah lebih jauh ke OOP, MineTile dapat mewarisi dari Tile generik).

Lapisan logika

Ini harus menampung cara-cara rumit yang akan digunakan aplikasi untuk berinteraksi dengan perubahan mode, menjaga status, dll. Jadi ini akan menjadi tempat pola mediator akan diterapkan untuk mempertahankan status permainan saat ini. Ini akan menjadi tempat di mana logika permainan berada untuk menentukan apa yang terjadi selama pertandingan berakhir misalnya, atau untuk mengatur MineTiles mana yang akan memiliki tambang. Itu akan membuat panggilan ke lapisan Entity untuk mendapatkan tingkat instantiated berdasarkan parameter yang ditentukan secara logis.

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];
 }
};

Lapisan layanan

Ini akan menjadi tempat di mana controller memiliki akses. Ini akan memiliki akses ke lapisan logika untuk membangun game. Panggilan tingkat tinggi dapat dilakukan ke dalam lapisan layanan untuk mengambil game yang sepenuhnya instantiated atau keadaan game yang dimodifikasi.

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();
}

Pengendali

Kontroler harus ringan, pada dasarnya inilah yang terpapar sebagai klien untuk model. Akan ada banyak pengendali, jadi penataan mereka akan menjadi penting. Panggilan fungsi pengontrol akan menjadi apa yang disebut panggilan javascript berdasarkan peristiwa UI. Ini harus memperlihatkan perilaku yang tersedia di lapisan layanan dan kemudian mengisi atau dalam hal ini memodifikasi tampilan untuk klien.

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());
};

Melihat

Pandangan harus diatur relatif terhadap perilaku pengontrol. Mereka mungkin akan menjadi bagian paling intensif dari aplikasi Anda karena berurusan dengan kanvas.

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();
}

Jadi sekarang Anda memiliki seluruh pengaturan MVC untuk game yang satu ini. Atau setidaknya, contoh sederhana, menulis seluruh permainan akan berlebihan.

Setelah ini selesai, perlu ada ruang lingkup global untuk suatu aplikasi. Ini akan menahan masa pakai pengontrol Anda saat ini, yang merupakan pintu gerbang ke semua tumpukan MVC dalam skenario ini.

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

Menggunakan pola MVC sangat kuat, tetapi jangan terlalu khawatir tentang mengikuti setiap nuansa mereka. Pada akhirnya, pengalaman bermainlah yang akan menentukan apakah aplikasi ini berhasil :)

Untuk pertimbangan: Jangan Biarkan Astronot Arsitektur Menakutkan Anda oleh Joel Spolsky


terima kasih @ TravisJ - Saya terangkat sebagai penjelasan yang bagus tentang MVC terkait dengan game. Masih belum jelas poin-poin tertentu, saya pikir, seperti yang Anda katakan, saya terjebak dalam nuansa pola dan itu menghentikan saya bergerak maju. Satu hal yang saya lihat adalah penggunaan this.view.Select () di controller - apakah jenis kopling ketat diperlukan atau apakah ada cara decoupling lebih lanjut?
cacing gelang

@wigglyworm - Selalu ada lebih banyak decoupling! : D Tapi sungguh, controller harus menjadi orang yang berkomunikasi dengan model dan kemudian memperbarui tampilan sehingga mungkin di mana sebagian besar kopling terjadi di MVC.
Travis J

2

Inilah yang telah Anda lakukan salah - Anda telah memutar MVC saat dalam keadaan kebingungan, dan tanpa MVC di bawah ikat pinggang Anda.

Lihatlah PureMVC, ini adalah bahasa agnostik dan bisa menjadi platform yang baik untuk membuat kaki Anda basah dengan benar-benar melakukan MVC.

Kodenya kecil dan dapat dipahami, dan ini akan memungkinkan Anda untuk menyesuaikannya dengan kebutuhan Anda saat Anda maju.

Mulailah menulis game sederhana kecil dengan itu, kapal penyapu ranjau akan baik. Banyak yang dikatakan Travis J bagus, terutama tentang Model. Saya hanya akan menambahkan bahwa Anda perlu mengingat bahwa Controllers (setidaknya di PureMvc) adalah stateless, mereka ada, melakukan pekerjaan SINGKAT mereka dan pergi. Mereka adalah orang-orang yang berpengetahuan luas. Mereka seperti fungsi. "Isi kisi, karena Model berubah", "Perbarui Model, karena tombol ditekan"

Tampilan (Mediator di PureMVC) adalah yang paling bodoh, dan Modelnya hanya sedikit lebih pintar. Keduanya abstrak implementasi, sehingga Anda (Pengendali) tidak pernah menyentuh UI atau DB secara langsung.

Setiap elemen UI Anda (seperti dalam aplikasi winforms misalnya) memiliki Tampilan (Mediator - Anda tahu mengapa ini istilah yang lebih baik sekarang?), Tetapi Mediator juga dapat dibuat untuk masalah meta seperti "Kontrol Warna" atau "Fokus" Manajer "yang beroperasi di seluruh elemen UI. Pikirkan berlapis-lapis di sini.

Acara UI dan DB dapat secara otomatis memanggil Pengendali (jika Anda menggunakan skema penamaan yang cerdas), dan Pengontrol tertentu dapat dihapus - Mediator dapat dibuat untuk secara langsung mendengarkan acara perubahan Data Model dan mengirimkan paket datanya.

Meskipun ini semacam cheat dan membutuhkan Model untuk mengetahui sedikit tentang apa yang ada di luar sana, dan Mediator untuk memahami apa yang harus dilakukan dengan paket data, tetapi itu akan membuat Anda tidak dibanjiri dengan Pengendali biasa dalam banyak kasus.

Model: Bodoh tetapi dapat digunakan kembali; Pengendali: Cerdas tetapi kurang dapat digunakan kembali (mereka ADALAH aplikasi); Mediator: Bodoh tapi bisa digunakan kembali. Dapat digunakan kembali dalam hal ini berarti portabel ke aplikasi lain.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.