자바 스크립트 MVC 애플리케이션 디자인 (캔버스)


9

Javascript에서 MVC와 같은 접근 방식을 사용하여 캔버스 응용 프로그램을 구조화 / 아키텍처하는 방법을 파악하는 데 어려움을 겪고 있습니다. UI는 상당히 유동적이고 애니메이션화되며 게임은 매우 단순하지만 트위닝 및 애니메이션에 중점을 둡니다. MVC는 원칙적으로 작동하지만 실제로는 작동하지 않습니다. 나는 이것에서 버거를 봤고, 끔찍한 많은 것을 읽었으며, 내가 처음 시작할 때와 마찬가지로 혼란스러워했다.

응용 분야에 대한 몇 가지 세부 사항 :

  • 멀티 스크린 게임 프레임 워크-여러 게임이이 프레임 워크 내에 위치합니다. 공통 UI "스크린"에는 설정, 정보, 난이도 선택, 주 메뉴 등이 포함됩니다.
  • 여러 입력 방법
  • 일부 화면의 상단 메뉴 표시 줄과 같은 일반적인 UI 요소
  • 다른 렌더링 방법 (canvas / DOM / webGL) 사용 가능성

현재 AppModel, AppController 및 AppView가 있습니다. 여기에서 각 "화면"을 추가하고 AppView에 연결하려고했습니다. 그러나 상단 메뉴 표시 줄과 같은 다른 MVC 트라이어드 여야합니까? 부품을 단단히 연결하지 않고 어디서 어떻게 부착 할 수 있습니까?

한 MVC 트라이어드를 다른 MVC 트라이어드 내에 두는 것이 허용되는 관행입니까? 즉, 각 "화면"을 AppView에 추가 할 수 있습니까? "트라이 아드"도 허용되는 MVC 용어입니까?!

선택의 여지가 제 마음에 녹고 있습니다. 여기에 근본적인 것이 빠진 것 같습니다. MVC 접근 방식을 사용하지 않고 이미 솔루션을 구축하고 실행했지만 수프-로직과 뷰가 밀접하게 결합되어 현재 결합되어 있습니다. 아이디어는이를 열어서보기를 더 쉽게 변경할 수 있도록하는 것이 었습니다 (예 : 캔버스보기를 DOM 기반보기로 교체).

사용 된 현재 라이브러리 : require.js, createJS, 밑줄, GSAP, 수동 롤 MVC 구현

특히 물건의 실제 디자인 및 "스크린"을 적절한 M, V 또는 C로 분할하는 것과 관련하여 모든 포인터, 예 등이 인정 될 것이다.

... 또는 MVC 이외의 적절한 방법

[NB,이 질문을 전에 본 적이 있다면 다른 2 개의 잘못된 스택 교환 커뮤니티에서 질문했기 때문입니다 ... 뇌가 기능을 멈췄습니다.]


1
마지막으로 올바른 사이트를 찾은 것 같습니다. Gamedev는 질문을 원하지 않습니까?
Robert Harvey

@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광산이있는 타일 중 하나 ( 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();
}

제어 장치

컨트롤러는 가벼워 야합니다. 기본적으로 클라이언트가 모델에 노출되는 것입니다. 많은 컨트롤러가있을 것이므로이를 구성하는 것이 중요해질 것입니다. 컨트롤러 함수 호출은 자바 스크립트 호출이 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();
}

이제이 게임에 대한 전체 MVC 설정이 완료되었습니다. 또는 최소한 뼈 전체의 예를 들자면 전체 게임을 작성하는 것이 과도했을 것입니다.

이 작업이 완료되면 어딘가에 응용 프로그램의 전체 범위가 있어야합니다. 이 시나리오에서는 현재 컨트롤러의 수명을 유지합니다.이 시나리오는이 시나리오에서 모든 MVC 스택의 게이트웨이입니다.

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

MVC 패턴을 사용하는 것은 매우 강력하지만 모든 뉘앙스를 고수하는 것에 대해 너무 걱정하지 마십시오. 결국, 응용 프로그램의 성공 여부를 결정하는 것은 게임 경험입니다 :)

고려 사항 : 건축 우주 비행사들이 Joel Spolsky에 의해 당신을 겁 내게하지 마십시오


@TravisJ 덕분에-게임과 관련하여 MVC에 대한 훌륭한 설명으로 찬성했습니다. 아직도 어떤 점이 확실하지 않다고 생각하는데, 패턴의 뉘앙스에 푹 빠져서 앞으로 나아갈 수 없게됩니다. 내가 본 것 중 하나는 컨트롤러에서 this.view.Select ()를 사용하는 것이 었습니다.이 유형의 단단한 커플 링이 필요합니까?
wigglyworm

@wigglyworm-항상 더 많은 분리가 가능합니다! : D 그러나 실제로 컨트롤러는 모델과 통신 한 다음 뷰를 업데이트하여 MVC에서 대부분의 커플 링이 발생하는 뷰 여야합니다.
트래비스 J

2

당신이 이미 잘못한 것은 다음과 같습니다. 혼란 상태에 있고 벨트 아래에 MVC가 없으면 MVC를 수동으로 굴 렸습니다.

PureMVC를 살펴보십시오. 언어에 구애받지 않으며 실제로 MVC를 수행하면서 발을 젖히는 데 적합한 플랫폼이 될 수 있습니다.

코드는 작고 이해하기 쉬우므로 진행하면서 필요에 따라 코드를 조정할 수 있습니다.

그것으로 작은 간단한 게임을 작성하기 시작하십시오. 지뢰 찾기가 좋을 것입니다. Travis J가 말한 많은 것, 특히 모델에 관한 것이 좋습니다. 컨트롤러 (최소한 PureMvc)는 상태가없고, 존재하며, BRIEF 작업을 수행하고, 사라 졌다는 것을 기억해야합니다. 그들은 지식이있는 사람들입니다. 그것들은 기능과 같습니다. "그리드를 채우고, 모델이 변경되었습니다.", "모델을 업데이트하십시오.

뷰 (PureMVC의 중재자)는 가장 어둡고 모델은 약간 더 똑똑합니다. 둘 다 구현을 추상화하므로 사용자 (컨트롤러)는 UI 또는 DB를 직접 만지지 않습니다.

UI의 모든 요소 (예 : winforms 앱에서와 같이)에는보기 (중개자-지금 이것이 더 나은 용어 인 이유를 알 수 있습니까?)가 있지만 "제어 색상"또는 "초점"과 같은 메타 인식을 위해 중재자를 만들 수도 있습니다. UI 요소에서 작동하는 관리자 ' 여기에서 레이어로 생각하십시오.

UI 및 DB 이벤트는 자동으로 컨트롤러를 호출 할 수 있으며 (스마트 명명 체계를 사용하는 경우) 특정 컨트롤러를 단계적으로 제거 할 수 있습니다. 중재자는 모델 데이터 변경 이벤트를 직접 수신하고 데이터 패키지를 전달하도록 만들 수 있습니다.

이것은 일종의 속임수이지만 모델이 무엇을 해야하는지에 대해 알고 있어야하며 중재자는 데이터 패키지로 무엇을 해야하는지 이해해야하지만 많은 경우 평범한 컨트롤러로 늪에 빠지지 않습니다.

모델 : 멍청하지만 재사용이 가능합니다. 컨트롤러 : 똑똑하지만 재사용이 적습니다 (앱입니다). 중재자 : 멍청하지만 재사용 할 수 있습니다. 이 경우 재사용 가능성은 다른 앱으로 이식 가능하다는 의미입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.