Thiết kế ứng dụng Javascript MVC (canvas)


9

Tôi đang gặp khó khăn trong việc nắm bắt cách cấu trúc / kiến ​​trúc một ứng dụng canvas bằng cách sử dụng phương pháp giống như MVC trong Javascript. Giao diện người dùng sẽ khá trôi chảy và hoạt hình, các trò chơi khá đơn giản nhưng chú trọng nhiều vào tweening và hoạt hình. Tôi hiểu cách MVC hoạt động trên nguyên tắc nhưng không thực tế. Tôi đã googled các lỗi về điều này, đọc rất nhiều, và bây giờ tôi bối rối như khi tôi bắt đầu.

Một số chi tiết về khu vực ứng dụng:

  • khung trò chơi đa màn hình - nhiều trò chơi sẽ nằm trong khung này "màn hình" UI chung bao gồm: cài đặt, thông tin, chọn độ khó, menu chính, v.v.
  • nhiều phương thức nhập liệu
  • các thành phần UI phổ biến như thanh menu trên cùng trên một số màn hình
  • khả năng sử dụng các phương thức kết xuất khác nhau (canvas / DOM / webGL)

Hiện tại tôi có một AppModel, AppControll và AppView. Từ đây tôi đã lên kế hoạch thêm từng "màn hình" và đính kèm nó vào AppView. Nhưng những gì như những thanh menu trên cùng, chúng có nên là một bộ ba MVC khác không? Tôi sẽ gắn nó ở đâu và như thế nào nếu không có các thành phần khớp nối chặt chẽ?

Đây có phải là một thực tiễn được chấp nhận để có một bộ ba MVC trong một bộ ba khác không? tức là tôi có thể thêm từng "màn hình" vào AppView không? Là "bộ ba" thậm chí là một thuật ngữ MVC được chấp nhận?!

Tâm trí tôi đang tan chảy dưới những lựa chọn ... Tôi cảm thấy như mình đang thiếu thứ gì đó cơ bản ở đây. Tôi đã có một giải pháp đã sẵn sàng và chạy mà không cần sử dụng cách tiếp cận MVC, nhưng đã kết thúc với súp kết hợp chặt chẽ - logic và quan điểm và hiện đang kết hợp. Ý tưởng là mở nó ra và cho phép thay đổi chế độ xem dễ dàng hơn (ví dụ: hoán đổi chế độ xem canvas với chế độ xem dựa trên DOM).

Các thư viện hiện tại được sử dụng: allow.js, createJS, gạch dưới, GSAP, triển khai MVC bằng tay

Bất kỳ con trỏ, ví dụ, v.v., đặc biệt liên quan đến thiết kế thực tế của sự vật và chia "màn hình" thành M, V hoặc C thích hợp sẽ được đánh giá cao.

... Hoặc một phương pháp phù hợp hơn ngoài MVC

[NB, nếu bạn đã thấy câu hỏi này trước đó bởi vì tôi đã hỏi nó trong 2 cộng đồng stackexchange không chính xác khác ... não của tôi đã ngừng hoạt động]


1
Có vẻ như cuối cùng bạn đã tìm đúng trang web. Gamedev không muốn câu hỏi của bạn?
Robert Harvey

@RobertHarvey nghĩ rằng nó có thể phù hợp hơn ở đây ... ít nhất là tôi hy vọng vậy!
wigglyworm

Câu trả lời:


3

MVC đã được bao phủ ở rất nhiều nơi vì vậy không nên lặp lại nhiều ở đây. Về cơ bản, bạn muốn biểu đồ đối tượng, trình trợ giúp và logic của bạn được chứa trong lớp mô hình. Các khung nhìn sẽ là các màn hình được đẩy ra để lấp đầy phần động của trang (và có thể chứa một lượng logic và trợ giúp nhẹ). Và bộ điều khiển, là một triển khai nhẹ để phục vụ các màn hình dựa trên những gì có sẵn từ các biểu đồ đối tượng, trợ giúp và logic.

Mô hình

Đây phải là nơi thịt của ứng dụng ngồi. Nó có thể được xếp thành một lớp dịch vụ, lớp logic và lớp thực thể. Điều này có ý nghĩa gì với ví dụ của bạn?

Lớp thực thể

Điều này sẽ chứa các định nghĩa về mô hình và hành vi nội bộ của trò chơi của bạn. Ví dụ: nếu bạn có một trò chơi dành cho người quét mìn, đây sẽ là nơi định nghĩa bảng và hình vuông cùng với cách họ thay đổi trạng thái bên trong.

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

Vì vậy, MineTile sẽ biết trạng thái bên trong của nó, chẳng hạn như nếu nó đang hiển thị hoặc đã được kiểm tra ( this.pristine), nếu đó là một trong những ô có mỏ ( this.hasMine) nhưng sẽ không xác định liệu nó có phải là của tôi không. Điều đó sẽ lên đến lớp logic. (Để đi xa hơn nữa vào OOP, MineTile có thể kế thừa từ một Ngói chung).

Lớp logic

Điều này sẽ áp dụng những cách phức tạp mà ứng dụng sẽ tương tác với việc thay đổi chế độ, giữ trạng thái, v.v. Vì vậy, đây sẽ là nơi mô hình hòa giải sẽ được thực hiện để duy trì trạng thái của trò chơi hiện tại. Đây sẽ là nơi logic trò chơi cư trú để xác định những gì xảy ra trong một trò chơi chẳng hạn, hoặc để thiết lập MineTiles nào sẽ có mỏ. Nó sẽ thực hiện các cuộc gọi vào lớp Thực thể để có được các mức khởi tạo dựa trên các tham số được xác định logic.

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

Lớp dịch vụ

Đây sẽ là nơi bộ điều khiển có quyền truy cập. Nó sẽ có quyền truy cập vào lớp logic để xây dựng các trò chơi. Một cuộc gọi cấp cao có thể được thực hiện trong lớp dịch vụ để truy xuất một trò chơi được khởi tạo hoàn toàn hoặc trạng thái trò chơi được sửa đổ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();
}

Bộ điều khiển

Bộ điều khiển nên có trọng lượng nhẹ, về cơ bản đây là những gì được đưa ra với tư cách là khách hàng của mô hình. Sẽ có nhiều bộ điều khiển, vì vậy cấu trúc chúng sẽ trở nên quan trọng. Các lệnh gọi hàm điều khiển sẽ là những gì các lệnh gọi javascript dựa trên các sự kiện UI. Chúng nên phơi bày các hành vi có sẵn trong lớp dịch vụ và sau đó cư trú hoặc trong trường hợp này sửa đổi các khung nhìn cho máy khách.

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

Lượt xem

Các khung nhìn nên được tổ chức liên quan đến hành vi của bộ điều khiển. Chúng có thể sẽ là phần chuyên sâu nhất trong ứng dụng của bạn vì nó liên quan đến canvas.

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

Vì vậy, bây giờ bạn có toàn bộ thiết lập MVC cho một trò chơi này. Hoặc ít nhất, một ví dụ xương cốt, viết toàn bộ trò chơi sẽ là quá mức.

Một khi điều này được thực hiện, sẽ cần phải có một phạm vi toàn cầu cho ứng dụng ở đâu đó. Điều này sẽ giữ thời gian tồn tại của bộ điều khiển hiện tại của bạn, là cổng vào tất cả các ngăn xếp MVC trong kịch bản này.

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

Sử dụng các mẫu MVC rất mạnh mẽ, nhưng đừng quá lo lắng về việc tuân thủ mọi sắc thái của chúng. Cuối cùng, chính trải nghiệm trò chơi sẽ quyết định xem ứng dụng có thành công hay không :)

Để xem xét: Đừng để các phi hành gia kiến ​​trúc sợ bạn bởi Joel Spolsky


cảm ơn @TravisJ - Tôi đánh giá cao đây là một lời giải thích hay về MVC liên quan đến các trò chơi. Vẫn chưa rõ ràng về một số điểm nhất định, tôi nghĩ, như bạn nói, tôi đang bị sa lầy vào các sắc thái của các mẫu và nó ngăn tôi tiến về phía trước. Một điều tôi thấy là việc sử dụng this.view.Select () trong bộ điều khiển - đây có phải là loại khớp nối chặt chẽ cần thiết hay có cách nào để tách rời hơn nữa không?
wigglyworm

@wigglyworm - Luôn luôn có thể tách rời hơn! : D Nhưng thực sự, bộ điều khiển phải là bộ giao tiếp với mô hình và sau đó cập nhật khung nhìn để có thể là nơi hầu hết các khớp nối diễn ra trong MVC.
Travis J

2

Đây là những gì bạn đã làm sai - bạn đã cuộn một MVC trong khi ở trạng thái nhầm lẫn và không có bất kỳ MVC nào trong vành đai của bạn.

Hãy xem PureMVC, đây là ngôn ngữ bất khả tri và có thể là một nền tảng tốt để làm cho đôi chân của bạn ướt với thực sự làm MVC.

Mã của nó là nhỏ và dễ hiểu, và điều này sẽ cho phép bạn điều chỉnh nó theo nhu cầu của bạn khi bạn tiến bộ.

Bắt đầu viết một trò chơi nhỏ đơn giản với nó, người quét mìn sẽ tốt. Rất nhiều điều Travis J nói là tốt, đặc biệt là về Người mẫu. Tôi chỉ nói thêm rằng bạn cần nhớ rằng Bộ điều khiển (ít nhất là trong PureMvc) không trạng thái, chúng tồn tại, làm BRIEF của chúng hoạt động và biến mất. Họ là những người hiểu biết. Chúng giống như các chức năng. "Lấp đầy lưới, vì mô hình đã thay đổi", "Cập nhật mô hình, vì đã nhấn nút"

Lượt xem (Hòa giải trong PureMVC) là ngu ngốc nhất và Mô hình chỉ thông minh hơn một chút. Cả hai đều trừu tượng hóa việc triển khai, do đó bạn (Bộ điều khiển) không bao giờ chạm trực tiếp vào UI hoặc DB.

Mọi yếu tố trong giao diện người dùng của bạn (ví dụ như trong ứng dụng winforms) đều có Chế độ xem (Người hòa giải - bạn có thấy tại sao đây là thuật ngữ tốt hơn bây giờ không?), Nhưng Hòa giải cũng có thể được tạo cho các mối quan tâm meta như "Màu điều khiển" hoặc "Tiêu điểm Trình quản lý "hoạt động trên các thành phần UI. Hãy suy nghĩ trong các lớp ở đây.

Các sự kiện UI và DB có thể tự động gọi Bộ điều khiển (nếu bạn sử dụng sơ đồ đặt tên thông minh) và một số Bộ điều khiển nhất định có thể được loại bỏ - Người hòa giải có thể được thực hiện để nghe trực tiếp sự kiện thay đổi Dữ liệu mẫu và được gửi gói dữ liệu.

Mặc dù đây là một mánh gian lận và đòi hỏi Người mẫu phải biết một chút về những gì bên ngoài và Người hòa giải phải hiểu phải làm gì với gói dữ liệu, nhưng nó sẽ giúp bạn không bị ngập trong Bộ điều khiển trần tục trong nhiều trường hợp.

Mô hình: Ngốc nhưng có thể tái sử dụng; Bộ điều khiển: Thông minh nhưng ít sử dụng lại (chúng là ứng dụng); Hòa giải: Ngốc nhưng có thể tái sử dụng. Khả năng sử dụng lại trong trường hợp này có nghĩa là di động đến một ứng dụng khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.