【发布时间】:2014-02-08 07:27:56
【问题描述】:
我正在制作一个简单的回合制太空游戏。玩家与代表星系/可玩区域的 2D 地图进行交互。地图由扇区组成,每个扇区可能包含许多行星。玩家可以通过将航天器移动到每个区域并根据需要进行殖民来与地图互动。
所以,我的模型层的一部分看起来像这样(为了简单起见,我在这里过于简单化了):
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
}
}
我现在只有一个控制器,MapController。它在键盘/鼠标上创建事件侦听器,以便玩家可以与地图交互,即:
- 玩家在 MapView 中点击一个扇区 -> 在 ExamineSectorView 中查看该扇区
- 玩家使用箭头键 -> 滚动地图相机。
在启动时,控制器调用 Map 上的方法(生成它),创建视图并启动 setInterval 计时器以进行视图渲染。
我想要帮助的是我的两个观点。
我觉得他们俩都做得太过分了。
它们确实包含逻辑,但它只是与视图相关的东西,并且是渲染所必需的 - 就像一个 10-switch 语句来确定行星类型并绘制适当的图像或行星的“.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,它包含它需要的所有视图并呈现每个视图。
谢谢!
【问题讨论】:
标签: javascript design-patterns model-view-controller separation-of-concerns