1

I've built a couple of 2D games that are roughly MVC; that is, the main game data and logic are separated into the model (and possibly controllers), and I have a bunch of screens/states that just pull stuff from the model class and draw that on screen.

This is not a complete separation, because things like size, collision detection, etc. tend to be view concerns and not model concerns.

In any case, I have a difficult time "gluing" together models and views. Is there a good way to do this, while still preserving the separation of concerns?

Let's say I'm working with a Sprite class to represent an image, and I have a Player class representing my player (X, Y, number of lives, running/walking, etc.). How do I associate them together?

For example, Player can be a subclass of Sprite, or can contain an instance of Sprite (or vice-versa), or I can have a third class (PlayerModelView) that contains an instance of both Player and Sprite, or something else entirely.

(I've tried the latter approach, but it usually ends with a lot of type conversions and the model checking with the view about collisions.)

ashes999
  • 11,261
  • 9
  • 59
  • 95
  • 1
    And this is why MVC doesn't really work for game development... – thedaian Dec 06 '11 at 19:32
  • @thedaian I disagree. MVC works very well with small projects, and makes it easy to port them to new platforms or game engines. But sure, you're entitled to your opinion :) – ashes999 Dec 06 '11 at 19:41
  • 1
    Sprite holds image data and therefore should be part of your model. – Exilyth Dec 06 '11 at 19:49
  • @sarahm that makes it very hard to unit-test "model" concerns (like health/lives/whatever) without knowing about or instantiating parts of the view. – ashes999 Dec 06 '11 at 19:58
  • @ashes999 why would it? – kaoD Dec 06 '11 at 20:28
  • @kaoD because you need to have a properly instantiated view. Look at XNA for example; if you want to create a sprite, you need to worry about embedded resources, SpriteBatch, etc. so subclassing and testing your player health without having all this infrastructure becomes very difficult. – ashes999 Dec 06 '11 at 20:32
  • 2
    Potentially (dependant on language and engine), you have two models - one for the Player's state (position, lives, and so on), and one for the Sprite state (frame, image offset, etc). The two models don't really have much to do with each other; wire them together with a controller as normal, and wire a controller for the Sprite-model to view translation. – Clockwork-Muse Dec 06 '11 at 21:21
  • @X-Zero please add your comment as an answer, that's what it is... – ashes999 Dec 06 '11 at 21:27
  • Indeed, sprite and player should be separate. Ideally, you'd only have a reference to a sprite or a spriteID in your player class. – Exilyth Dec 06 '11 at 21:56
  • I never understood the appeal of MVC in game development. Your point on your Radiant Wrench page about rewriting views for different platforms makes sense, but I feel there must be a more convenient way to compensate for platform display idiosyncracies that would be much more intuitive to work with. – michael.bartnett Dec 07 '11 at 00:25
  • @bearcdp MVC works great in non-gaming apps, and I can see that a lot of the benefits from there would apply to gaming. When I find something that works better, I will happily drop MVC for it. Unit testing is a big part of it for me, and MVC enables that. – ashes999 Dec 07 '11 at 00:49
  • 1
    I understand the value of unit testing in games, like being able to run checks against your game logic, and, to a less thorough extent, physics and collision. But wouldn't it be just as easy with any sort of logic and rendering separation? I've been playing with the entity component design used in Artemis, and since it's comprised of strictly data (Components) and logic (Systems), you can unit test the Systems and ensure the Components have valid data. The view would effectively just be another controller albeit one you can't really write an automated test for (assuming use of a graphics lib). – michael.bartnett Dec 07 '11 at 05:31
  • @bearcdp I don't really understand your comment. My experience with MVC and games has been that it's hard to test when you have view classes peppered in everywhere. I'm looking for a design that will allow me to do that easily by decoupling from the view, that's all. – ashes999 Dec 07 '11 at 14:26
  • 1
    My point is keeping your view/display/render-oriented classes organized separated from your logic classes is not something exclusive to MVC. MVC may accomplish that, but MVC also carries impplementation style baggage with it. I feel like games I've worked on, even those with clearly separated display/logic/data layers rarely are able to cleanly fit their code modules into categories of model, view, controller, viewmodel, modelview, or whatever. I could see myself having to create a lot of redundant classes in order to fit the architecture pattern. – michael.bartnett Dec 07 '11 at 22:51
  • @bearcdp if you have a better idea, post an answer. That's what this question is for. – ashes999 Dec 07 '11 at 23:19

1 Answers1

4

When doing MVC-style architecture (not just in gaming!) it can be helpful to remember that there is often more than one model. Besides the (usually) obvious model of the Player's state (his position, life, and so on), there may be models (dependant on language and engine) for Sprite, or other 'display' classes.

For instance in Valve's Source engine, the 3-dimensional art (and animations) are encapsulated in their own files (representing the mesh, current animation, a few other things, but not the object's position), and have absolutely no relation to an entity's data (which contains position, orientation, and so on).

Because the two models usually don't (or aren't supposed to) have much to do with each other, they can (or possibly should) be wired together with seperate controllers: One for Player model to Sprite model updates (setting the currently playing animation, display position, etc), and one from the Sprite (for what, and where relative to other display elements) model to the view.

Here's a quick (Java-based Psuedo-code) example with attributes:

public Beast {
    private String name;
    private List<Behaviour> behaviours;  
}

public Player {
    private List<Beast> paddock;
    private List<Beast> leashed;
    private List<Beast> hospital;

public BeastAnimation { // One per beast!
    private Map<Behaviour, Animation> animations;
    private Animation current;
}

With these entities, you'd want a controller that would set the BeastAnimation's current based on whatever Behaviour was being executed - depending on game type, you usually need to start the animation even if the object is otherwise not (at least initially) visible, you don't want the entity doing nothing the first time he's seen (especially if the animation is long). Please note that this doesn't necessarily mean rendering the animations or (depending on display type) even applying transforms.
You're also going to want a controller that takes the 'current' BeastAnimation when actually rendering out the animation. Please note that the various animations only their relative positions, and shouldn't really know where the camera is - this controller acts as the necessary translation bridge. It's good to note that a fair number of graphics engines essentially take care of this for you - you only have to hand it the necessary models/animations, and say where the camera is - they're a controller/view package in one. Otherwise, how (and what the necessary translations are) varies by case

Clockwork-Muse
  • 241
  • 1
  • 4
  • I'm in 2d, not 3d. So your solution is basically to create a class for the model (Beast), a class for the view (BeastAnimation), and a "glue" class to connect the two (Controller?) – ashes999 Dec 08 '11 at 02:44
  • @ashes999 - BeastAnimation isn't a view - it's another model; specifically, one containing view-related data (so, a model of the view). If I've done the rest of the work right, I can change from 2d to 3d (or vice versa) simply by switching out the view and whatever the various Animations contain - no other part of my code has to change (supposing that gameplay doesn't change...). Every (non-trivial) view is going to be backed by models specifically for the view of some sort. This potentially includes text-based adventures... – Clockwork-Muse Dec 08 '11 at 16:51