0

我正在製作一個簡單的基於回合的空間遊戲。玩家與代表星系/可玩區域的2D地圖相互作用。該地圖由部門組成,每個部門可能包含多個行星。玩家可以通過將航天器移動到每個區域並根據需要定殖來與地圖進行互動。正確處理MVC javascript遊戲中的多個視圖

所以,我的模型層的部分看起來像這樣(我在這裏簡單化僅僅是短暫的):

function Map() { 

    // An array of Sectors 
    this.sectors = []; 
    . . . 
} 

function Sector() { 

    // Array of Planets 
    this.planets = []; 

    // Array of player built space stations 
    . . . 
    this.spaceStations = []; 
} 

function Planet() { 

    // Array of player built buildings 
    this.structures = [] 
    . . . 
} 

遊戲目前有兩種觀點,這使得可見宇宙中的MapView:

function MapView() { 

    // @param _map The game Map object 
    this.render = function(_map) { 

     this.canvas = new Canvas(); 

     // Camera can examine the Map to find the part that is currently visible on screen 
     this.camera = new Camera(); 
     . . . 

     foreach(_map.sectors as sector) { 

      LOTS of code and drawImage commands here to . . . 
      -ask camera if each sector is in currently in view (no point drawing the entire map) 
      -draw each sector background image (star field or nebula or whatever helps make the game look more natural) 
      -draw sector boundary lines so we end up with a nice nasty grid over the whole map 
      -determine what planet sprite image to draw depending on planet type (i.e ROCK, EARTH, GAS) 
      -draw every planet in each sector (the player can watch these planet sprites ‘orbit’ their sun) 
      -draw any player created structures in each sector 
      -draw any ships currently in each sector 
     } 
    } 
} 

和ExamineSectorView,這使得一個選擇的扇區:

function ExamineSectorView() { 

    // @param _sector A game Sector object 
    this.render = function(_sector) { 

     this.canvas = new AnotherCanvas(); 
     . . . 
     not-so-much-but-growing-suspiciously-large-amount-of-code here to . . . 
     - foreach { draw planets in currently selected sector (selected from Map) } 
     - draw space stations 
     - you get the idea 
    } 
} 

views

我現在只有一個控制器,MapController。它的鍵盤/鼠標創建事件偵聽器讓玩家可以與地圖,互動即:

  • 在MapView的一個部門玩家點擊 - >查看在ExamineSectorView
  • 玩家部門使用箭頭鍵 - >滾動地圖相機。

在啓動時,控制器調用Map上的方法(生成它),創建視圖並啓動一個setInterval計時器以進行視圖渲染。

我想幫忙的是我的兩個意見。

我覺得他們都做得太多了。

它們確實包含邏輯,但它僅僅是視圖相關的東西,並且僅用於渲染 - 就像10個開關語句一樣,用於確定行星類型並繪製適當的圖像或者一個行星的'.size'屬性來計算繪製它有多大。所以我認爲,邏輯是在正確的地方。

問題是,所有這些視圖特定的邏輯加起來很多。我的觀點已經失控,希望以某種方式將觀點的各個方面的表現分開。例如,像這樣:

function MapView() { 

    this.render = function() { 

     this.canvas = new Canvas(); 

     // Camera can examine the Map to find the part that is currently visible on screen 
     this.camera = new Camera(); 
     . . . 

     foreach(_map.sectors as sector) { 

      mapSectorView = new MapSectorView(); 
      mapSectorView.render(sector); 
     } 
    } 
} 

function MapSectorView() { 

    this.render = function(_sector) { 

     this.canvas = new Canvas(); 

     . . . 

     foreach(sector.planets as planet) { 

      planetView = new MapSectorPlanetView(); 
      planetView.render(planet); 
     } 
    } 
} 

function MapSectorPlanetView() { 

    this.render = function(_planet) { 

     this.canvas = new Canvas(); 

     . . . 

     foreach(planet.structure as structure) { 

      structureView = new StructureView(); 
      structureView.render(structure); 
     } 
    } 
} 

. . . 

我已閱讀本網站上的其他帖子,狀態視圖不應該創建另一個。如果是這樣,上述替代方案將是在控制器中創建所有必需的視圖並開始傳遞它們;即

mapView.render(mapModelObject, mapSectorView, mapPlanetView); 

我不太確定那是解決這個問題的方法。

我可以想象這個遊戲會變得相當快速,而且我知道在我開發遊戲時視圖會變得更加複雜,所以我會很感激關於如何在這樣的MVC遊戲中管理渲染的任何建議,特別是關於在JS/canvas環境中分離問題。

我才發現:MVC: Data Models and View Models

我想如果這是這裏的可能的解決方案;創建一些視圖模型,即MapViewModel,它保存所需的所有視圖並渲染每個視圖。

謝謝!

回答

0

我認爲ViewModel方法是最好的選擇。

我現在有以下:

UniverseDomainObject(和類似 '行星' 其他雜項域對象)

  • 創建域;恆星,行星等(沒有像素這裏值,即位置在範圍0.0 - 1.0)

GameController

  • 實例化UniverseDomainObject
  • 實例化MainMapViewModel
  • 呼叫MainMapViewModel.prepare(universeDomainObject )在每個遊戲渲染循環中調用
  • 偵聽來自MainMapViewModel的(player input)事件並調用域方法appropri ately

MainMapViewModel

  • 實例化渲染器不可知照相機(基本上爲 '地圖' 滾動/縮放更容易的操作的一組方法/屬性)
  • 實例化MainMapView - 通過相機
  • 根據模型「尺寸」計算總像素大小(以像素爲單位)
  • 設置精靈的基本像素尺寸(starSizeInPixels,planetSizeInPixels等)
  • 在每個渲染週期:

    • 決定繪製哪些項目(它們是相機的視圖)
    • 計算像素位置/每個項目來繪製的大小之內;基於模型,像素大小和相機位置/縮放的位置
    • 創建一個POJO陣列 - 精靈 - 包含每個對象的計算位置/大小和圖像
    • 調用MainMapView。渲染(spritesList,_cameraData)
    • 偵聽輸入併發布適當的事件,以GameController

MainMapView

  • 創建畫布相機尺寸
  • 在每個渲染週期:

    • 迭代通過精靈列表,並呈現每個圖像以帆布

該解決方案合作得非常好爲止。當我添加更多視圖(即SectorView)時,MainMapViewModel可能仍然會變得相當大,但它確實允許我保持MainMapView完全啞。

MainMapView只是迭代通過POJO列表並呈現每個'精靈'它自己的畫布。它也有一個非常少量的特定於畫布的旋轉代碼來使行星繞着它們的恆星運行。

MainMapViewModel完全不瞭解MainMapView中的畫布邏輯。這很酷,也許我可以切換到OpenGL渲染器而沒有太多問題。

我使用簡單的Observable/Listener方法將事件發送到GameController;因此它現在更加專注於「遊戲」事件而不是特定的按鈕輸入。

我在考慮將MainMapViewModel分成不同的類。目前它爲從星系和星星到月亮和空間站的所有事物準備渲染數據。將這些東西分成單獨的類而不是一個大塊的代碼會很好。另一方面,它準備的渲染數據視圖正確渲染所需的一切,所以它應該有我認爲的單一責任。

我會很感激任何意見,尤其是關於我的MainMapViewModel的實現和職責。它承擔了太多的責任嗎?我在圍牆上。