- The model manages the behaviour and data of the application.
- The view presents the model to the user.
- The controller passes user input to the model and view.
- In the Apple documentation where I learned about MVC, they also push that part of the controllers job is to get their model onscreen, so views shouldn't see their models, they should be generic and get their information via the controller.
Working with a particular design pattern really reminds me of what it's like to work on a code library, or a game engine. It's all neat and tidy, essentially because it's never seen the light of day. Once they're exposed to those pesky real-world scenarios, that's when the code starts to get messy, and MVC is no exception.
I was trying to figure out how I might go about using MVC for a game, and one of the things I really like about it is that with the decoupled views, I could for example take a 2D game and make it 3D by writing some new views. But I found myself wondering, what if I wanted to unplug a view, and plug a different one in on the fly? This would possibly require having the controller support multiple types of view - but this is ugly to maintain, you end up with lots of:
if( this->view->GetType() == "View2D" )
{
// Do 2D view stuff
}
else if( this->view->GetType() == "View3D" )
{
// Do 3D view stuff
}
Or you put all of the user input code into one class, and then create 2 subclasses - one for the 2D view, one for the 3D view. But then what if you have controller class hierarchy like:
- Controller
- PlayerController
- PlayerControllerKeyboardAndMouse
- PlayerControllerXboxGamepad
- PlayerControllerTouchscreen
So I'm going to create two versions of each of the last three classes to support both view types am I? Am I bollocks. OK so some might be thinking "who on earth is going to go from 2D to 3D on the fly", but the ability to switch views at runtime like that has proper real-world applications. Take for example the cooperative AC130 mission in Call of Duty: Modern Warfare 2, both players are most likely looking at exactly the same data in terms of models, but one is seeing higher detail meshes and textures from a first-person perspective, and the other is looking down from the sky on a lower poly, black and white representation of the same thing. Though it doesn't happen in that particular example, it's not unreasonable to imagine a game scenario where you'd want to switch perspectives on the fly.
So, did I throw MVC out the window? Well no, not entirely, I just changed it to better fit my needs. This is the thing I want to get at, well.. Two things really:
- Thing the first - never set out with a pattern in mind before thinking about the needs of the particular project, just because you have a favourite pattern, doesn't mean it will be right for everything you work on.
- Thing the second - a pattern is not a one size fits all solution. Don't feel you have to stick to the almighty rules of the pattern even if they're a pain! A pattern is a starting point, it's something that worked for somebody else, somewhere else, making something else. The chances are that your particular project will have some specific needs that will need to be factored in to the overall architecture of your code.
Here's the thing I wish I learned at university - if your nice shiny plan for your software doesn't work out, it doesn't mean you failed. Game development is often a very iterative process, it doesn't matter how long you mess around with flow-charts and diagrams, "No battle plan survives contact with the enemy". So just get on and code, go back to drawing board as and when you need to, and retrofit existing code to reflect architecture changes.
To be honest, that's where this post should end, from here on it's mostly rambling. For anyone bored enough to read on, or wondering what changes to MVC I felt necessary, here they are:
- Controllers don't directly change the model, they just provide abstract influence - e.g. the model might call this->controller->GetDesiredMovementSpeed()
- Views are specialised, so the controller doesn't need to worry about setting them up
- Views have read-only access to the model they are representing
What I couldn't figure out, is what if I've got flower power, and I shoot a fireball? Mario's model creates the fireball's model, but how does its view get set up? Mario's model can't do that, because that's coupling model code with view code. So I found the article by the power of google, but it actually doesn't answer the question directly, but I sent the author an e-mail and he was kind enough to explain it to me.
"In our code, the RepresentationManager gets notified when an entity is added to the EntityManager (it could be a generic listener on the EntityManager). It then creates the EntityRepresentation.
For that you'd use a factory pattern. Something like:
map = { { "Entity", "EntityRep" },
{ "EntityTypeA", "EntityTypeARep" },
...
}
RepresentationManager::OnEntityAdded(Entity *e)
{
string rep_type = map[e->GetType()];
EntityRep *rep = factory->Create(rep_type)
...
}"
In theory this would also be possible with views which are more generic, where the map would take a model type as a key, and a view config as the value:
{
"Mario" : { "type" : "TextureView", "texture" : "mario.png" }
}
// As opposed to..
{
"Mario" : "MarioView"
}
Anyway, quite possibly I'll eat my words in a years time, or perhaps the game I'm working on will have an architecture even further removed from MVC. Who knows, or cares? I'm going to bed.







