When programming a new game, most of the time you implement some basic features and start from there. As the game gets bigger, your code gets more interwoven, and the classes bigger. And before you know it you end up with spaghetti code and god classes, and that’s the last thing anyone wants.
Let’s assume we’re programming a racing game, and we have a class called RaceCar. Soon enough that class will contain a method to update it’s state, to draw it onto the screen, to accept user input, etc. It will become huge with all kinds of different functionality in there. So how can we divide up our game so it’s nicely split up into modules and classes? Just read on and learn ;).
Step 1: Split up the game into logic and rendering
Concept
The first thing we should do is decouple the rendering from the logic. And this makes perfect sense. If you take look at my game loop article, we can even let the game logic run at a different speed than the rendering.
The game logic will know nothing about the rendering, so it doesn’t matter if it will be displayed in 2D, 3D, ASCII art or whatever. The rendering however depends on the logic, because it needs info on how/where to display everything. The following figure shows the 2 modules with their dependencies. The rendering happens inside the “View” module.
_________ _________ | | | | | Logic |<-------| View | |_________| |_________|
Example
What this means in practice is that we will create a RaceCarView class next to our RaceCar. RaceCar handles the logic and user input, and knows nothing on how to display it, and RaceCarView displays the race car on the screen, using information from RaceCar.
Problem with interaction
When our car is controlled by a joystick or keyboard this concept works out just fine. But assume we want to mouse click on an opponent car to take over its control. If our logic knows nothing about the view, we don’t know on which car the user clicked. So in this case our logic also needs to query the view, which creates a circular dependency, and we don’t want this. Lucky for us we can get rid of this by doing another split, explained in the following section.
Step 2: Split up the logic into model and controller
Concept
The second thing we can do is further split up the logic into a model and a controller. The model is basically the game world, it knows nothing about displaying, user input, etc. It just implements all the world rules, and how entities interact with each other. The controller knows about the model and can manipulate it. For example the controller checks the user input, and manipulates the car accordingly. As we saw in the previous section, the controller needs to query the view when using mouse input for manipulating on-screen objects. And thanks to the split up, the model doesn’t have any dependencies like the logic had.
________________ | | | Controller | |________________| | | | | | | ______V__ __V______ | | | | | Model |<-----| View | |_________| |_________|
Example
In our RaceCar example, we will extract our user input handling into a new class RaceCarController. When the user presses the left-button, the controller sees this and calls the model’s RaceCar.steer_left(). The model then handles the world rules of the car going to the left.
Where to put the AI?
Most games use an AI to control certain game objects, so the question is where to implement this, in the model or the controller? The answer is pretty simple: if the AI controls the same object in the same manner as the user does (i.e. a ‘bot’), implement it in the controller. In the other case, it’s part of the game world so you should implement it in the model. In our example the car AI’s should be implemented in the controller, because they are basically bots. If we would have pedestrians that jump out of the way, they would be implemented in the model, because they are part of the world.
Summary
So after dividing our code up we get 3 separate modules: the model, the view and the controller.
- Model
- All the rules of the game world are implemented in the model, and it also contains the state data of every game object or entity. It is a pure game world simulation, so it doesn’t know anything about user input or displaying to a screen.
- View
- Rendering to the screen is handled by the view. It uses the model to know where to draw everything. The view doesn’t have any other functionality than this.
- Controller
- The controller handles the user input and manipulates the model. First it checks for user input, then it might query the view to see which on-screen objects are being clicked by the mouse, and finally it manipulates the model. Multiple controllers can be implemented, for example a keyboard controller, joypad controller, and even AI ‘bot’ controllers.
The model is standing on it’s own and doesn’t need to know anything about the others. The view depends only on the model to render everything on the screen. The controller receives input, can gain additional information by calling the view, and at the end manipulates the model. The advantages of this architecture:
- Nice modular design
- Game world logic is nicely bundled in the model
- Changes in rendering doesn’t impact the core game
- Supports different input controllers and/or bots
________________ | | | Controller |<============ User Input |________________| | | O | | /|\ | | / \ ______V__ __V______ | | | | | Model |<-----| View |=======> Screen Output |_________| |_________|
Koen Witters
12 Comments
Sebastien B · July 16, 2009 at 10:01
Great post, thanks!
On the same subject, read this one too:
http://www.gamasutra.com/features/20050414/rouwe_01.shtml
Newton · August 13, 2009 at 05:31
the ides is great!
I think practice is the best way to master MVC
zyhang · August 25, 2009 at 20:25
thanks! it is useful for beginner
Spued · August 31, 2009 at 20:19
Thank you. This is very useful for me.
Rodrigo Bento · September 2, 2009 at 13:50
Dudes,
Wouldn’t all these classes/objects that are needed to implement this pattern kind of slow down the update and draw of the game. I mean all these messages between objects and getting and setting values…
I read the article Sebastian suggested about Guerrilla Games and the MVC patten and they mention a certain overhead regarding this topic.
Will this overhead kind of slow down the update or drawing? In that case what would be the approach to deal with this. What you guys think about it?
Glen Schulz · September 11, 2009 at 14:00
Great article, thanks!
Here’s another great article on Main() loop implementations, and separating game update from rendering and FPS:
http://dewitters.koonsolo.com/gameloop.html
Noir Talon · September 19, 2009 at 12:44
MVC is a great way to start, the model scales well to online and MMO games. Check out some of the architecture’s used in MMOs like EvE, WoW, and the like.
I’ve got some examples posted at pennymo.com from a presentation I gave on MMO architecture at MIGS 2008.
Vishwas · August 4, 2010 at 08:49
Say, i have a button on my gui, then where should i put the reference to my button ? In view or in controller. Where should it’s onRelease event be registered ( controller or view?). And what is the placement of the function, where it would be broadcasted ( controller or view?)
Thanks.
Niriel · June 14, 2011 at 06:05
Maybe I overdid things, but my view never touches the model and knows nothing about it. For example, my DudeSprite instance does not contain a pointer to my DudeModel instance. Instead, my DudeSprite listens to DudeMovedEvent instances that contain dude_id and a position (all floats, integers, strings lists or other simple types that JSON could handle).
I found that useful when I started to split my game into a network/server architecture. The DudeModel is on the server. I may put a DudeModel on the client as well and in that case the one on the server is authoritative. But now, I can have my DudeSprite in a different process and even different machine than the DudeModel. They speak exchanging light weight messages.
Maybe this will create a huge overhead, but it gives me a lot of flexibility. I’ll optimize only if necessary, not before.
umme · November 8, 2016 at 06:24
sir we need the architectural model for game how we define things in it
dkv · March 25, 2018 at 06:42
tnx its useful
Montgomery · April 16, 2018 at 13:21
This was very helpful. I am grateful for the clarity of interaction between the M V and C