Sign in to follow this  
Zarion

Model/View seperation and serializing data relevant only to the view

Recommended Posts

Lately, I've resumed working on an outline of the basic system architecture for a turn-based tile-based strategy game I'm developing, and I'm having some issues with the separation of model/view. Specifically, a piece of data which has relevance only to the view, but which, at first glance, needs to be tied and serialized persistently with elements in the model.


Here's a little overview of the relevant parts of the architecture:

In the model, maps are strictly grid-based, and no unit can exist between grids. A unit is either in one tile or the other. If it moves, it instantly occupies the next step along its path. In the visualization, this is untrue, and units are shown moving between grids, animated while attacking, and so forth. Thus, the model maintains a list of units in world-coordinates, while the view maintains a separate one in screen-coordinates.

The model communicates with the view by passing messages corresponding to game events. For example, telling it that a unit moved from location X to Y, or that unit X attacked unit Y for Z damage. The view receives these message, and then uses its own logic to decide how to render them (or, indeed, if they should be rendered)

It is the view's responsibility to know which of its sprites each of the game units referenced in the messages corresponds to, so that it knows which to move/animate. In general, it looks at data in the model once, to construct its list of sprites, and then simply operates on its own representations in response to messages.

Since the model need know nothing about the view, and will happily pass these messages to any registered recipient, this allows the creation of alternative interfaces, but more interestingly, easily facilitates storing detailed logs and replays of games, or running simulations that can execute in the absence of any display.


The issue I'm grappling with specifically is how to handle terrain tile graphical variants.

In the model, the terrain layer is stored as a grid of base types (eg: TERRAIN_GRASS, TERRAIN_ROCK, etc.), with whatever properties specifically affect game logic. When loading a level, the view looks at the map contained in the model, and then does a lookup for each base type to figure out what tile it should use to render it. Many base types are associated with multiple tiles, to provide graphical variants. For example, there could be 5 different ways to draw a TERRAIN_GRASS tile. The issue is that which of these variants is used for a particular tile should remain persistent both within a single game session and between them. If that rock wall had a small crack in it, it should not suddenly exchange it for a completely different looking one when it scrolls off screen, or you reload a saved game.

However, given that the rendering information and sprite list for a given map is constructed on-demand from data supplied by the model, there seems no immediate way to achieve this without breaking the model/view separation. Basically all other persistent map data is stored and serialized by the model, but tileVariantID is a property that has strictly no relevance to the model, only the view. Worse, it is tied to a specific view implementation. In order to know what range of IDs is valid for a given terrain type, it must know how many variant graphics there are for that terrain type.

An alternative seems to be to have the view serialize a grid of tileVariantIDs itself, after it assigns them when a map is first retrieved from the model. Perhaps there's nothing inherently wrong with this, but something about it strikes me as unpleasant, given that the view is generally not concerned with storing persistent data itself: it simply presents data that is stored in the model. That's its job. This would effectively introduce a second data source, external to the model.

Any thoughts?

Share this post


Link to post
Share on other sites
Quote:
Original post by Zarion

In the model, maps are strictly grid-based, and no unit can exist between grids. A unit is either in one tile or the other. If it moves, it instantly occupies the next step along its path. In the visualization, this is untrue, and units are shown moving between grids, animated while attacking, and so forth. Thus, the model maintains a list of units in world-coordinates, while the view maintains a separate one in screen-coordinates.

Not really. "Real" units are those in the game model, the view owns screen-space animations that refer to them.
When you save the model, units are not in the middle of a move; such an animation can be reconstructed and replayed if needed by storing "before" and "after" model states.
Quote:
Original post by Zarion
When loading a level, the view looks at the map contained in the model, and then does a lookup for each base type to figure out what tile it should use to render it. Many base types are associated with multiple tiles, to provide graphical variants. For example, there could be 5 different ways to draw a TERRAIN_GRASS tile. The issue is that which of these variants is used for a particular tile should remain persistent both within a single game session and between them.


Whatever algorithm picks tile variants randomly can be seeded the same way with a bit of care and regenerate the same output for the same (reloaded) map data: just make it independent of how the order in which tiles are processed or other accidental details.

For example, you can choose one of N variants for the terrain at (x,y) with (x^y)%N or some better hash function combining x and y and possibly adjacent terrain types (to break patterns).

Share this post


Link to post
Share on other sites
Quote:
Original post by LorenzoGatti
Not really. "Real" units are those in the game model, the view owns screen-space animations that refer to them.
When you save the model, units are not in the middle of a move; such an animation can be reconstructed and replayed if needed by storing "before" and "after" model states.


Perhaps my terminology was off, but that's what I meant. None of that is persistent since, as you say, units never really occupy in-between spaces.

Quote:
Original post by LorenzoGatti
Whatever algorithm picks tile variants randomly can be seeded the same way with a bit of care and regenerate the same output for the same (reloaded) map data: just make it independent of how the order in which tiles are processed or other accidental details.

For example, you can choose one of N variants for the terrain at (x,y) with (x^y)%N or some better hash function combining x and y and possibly adjacent terrain types (to break patterns).


That's an interesting idea and does address most of the given concerns, I think. I wonder, though, for units themselves (some of which also have variant appearances), it obviously cannot be tied to place... but a unique identifier for each unit, guaranteed to remain constant across sessions, would probably function just as well.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this