Why MVC Is Not an Ideal Model for Games
Once your program has a main loop, structuring code becomes significantly more important. There are only so many ways you can structure a simple filter-like program[1]. We can consider each page or API of a web application as a filter-like program. But when you think about it as a whole MVC makes a lot of sense for web applications. Next tier in interactivity is native GUI apps, this is where MVC shines. In fact, if you are using a GUI toolkit you are probably interacting with a MVC model. In the realm of computer programs games are as complex as the interactivity gets. I will try to make the case that MVC is not an ideal model for games.
“Almost all computer games exhibit a very clear MVC, with a literal controller which is physically separate both from the view (ie, TV or monitor) and the modelling unit (the CPU/box, with its internal representations of the game components).”
—TWW on C2
Before I start, I’d like to summarize my infinitesimal experience in game development. I had mentioned before, in my first game, the primary building block used to be screens. It was a mess until I refactored the whole thing to use MVC. I was definitely an improvement but it still didn’t feel quite right. Only when I found out about a better architecture, I started to realize MVC wasn’t the best approach for games.
One more thing I should mention; when I say using MVC, I mean using MVC as the top level architectural model. There is nothing inherently wrong with MVC. And there can be parts of your game that MVC is the best way to model.
Change Is Frequent and Substantial
In business applications you can usually do one thing at a time. For instance in an accounting application you can add or edit an invoice, one invoice among potentially thousands. Even if it’s a client server application and a number of users are connected all at the same time a very small part of the data, the program’s state, is being modified. In this case it makes sense for a client subscribe and wait for events because there is not much point in polling the the data repeatedly if it’s not rapidly changing.
In a typical game objects we are interested in are changing constantly. If they didn’t, they wouldn’t be so interesting. So instead of listening for events, sometimes just assuming they have already changed yields faster programs.
I am not saying events are useless in games, there should be at least a win event and a lose event, right? But in an interesting game a number of things happen in each tick[2]. Routing these through an event system would waste precious cycles if we know we need to do some calculation now!
Views and Models Are Much Closer
In games, abstract representations and their concrete, user facing implementations are very much alike. This is because you are not starting with an abstract concept (checks and balances) and building an application on top of it. When you are making a game you start with an (imagined/designed) concrete result and build a software simulation underneath.
For instance a text box in a GUI application would remember start and end indices of characters selected, it might even cache position and the size of the selection marker for faster drawing. In a game, say a 2D platformer, the position of your character’s sprite would be stored as x and y coordinates. When you draw this character the view would either have to duplicate this data (it might make sense since the position might not be modified every frame) or to reach out and read it from the model every time even if it’s not changed.
One of the strengths of MVC is the representations can be replaced without modifying the business rules. In a game you don’t need this flexibility. Unless it’s a very special game, it doesn’t need a command line interface and a web interface as well as a native GUI.
Models’ Dependency on Views
Suppose you are working on a 2D game and want to perform hittests. Your models can hold bounding box information and you can use it for collision detection. But what if for your objects, a simple bounding box test just isn’t good enough and you need pixel precision? You need to access the sprites but aren’t they presentation, part of the view layer?
This is closely related to the previous point. Of course you can arrange things in such a way that pleases the gods of MVC. But then you would either end up duplicating almost everything in your views and models or perform redundant reads from your view.
Conclusion: Horizontal vs. Vertival
MVC is often confused with three tiered architecture. Although they are quite different concepts, their components are somewhat similar. I’d like to think, structurally, not in dataflow-wise, MVC organized a system in pieces layered on top of each other. Like a 3-tier architecture. And everything goes into one of those three components, which are hopefully well organized within.
In a game system this seperation doesn’t really make a lot of sense. Because a single object’s data, behaviour or presentation doesn’t have a lot of relevance. It would make sense to deal with an object as a whole, data, behaviour and presentation. But that wouldn’t go too far either. Because the whole point of a game is the interaction of objects. The focus is on the relationships of these objects. Cut your system vertically and it becomes hard to capture those interactions.
I am using the term system intentionally here. A game is essentially a simulated system. It usually starts from a more or less known state and after the objects within interact with each other for some time it reaches one of the final states, hopefully a win state. This is why it makes sense to structure the application in sub-systems. The way I visualize this is to hack it into vertical pieces. Each piece encapsulating one kind of interaction. Each subsystem dealing with all the relevant objects.
An entity/component system as the top level structure is much better than MVC for games. MVC can still be useful as a piece of the puzzle, especially when a classical UI involved.
[1] | By filter-like I mean; a program that reads some input, does something with it and writes the output somewhere. Linux command wc is an example. |
[2] | Not all of these have to be rendering events. It can be A.I. of for instance. |
If you have any questions, suggestions or corrections feel free to drop me a line.