Skip to main content

How can you organize the code for a game to fit the MVC pattern?



I'm a freshman in college going for my computer science degree... I've programmed plenty the last several years but just lately I've been getting more into theoretical ideas about organizing code, design patterns, differences in languages, etc.





I have a Java class, so I've dropped my C++ research/development and moved into Java and JOGL (Java OpenGL). It's wonderful! But that's beside the point.





I want to make a small role-playing game, but this question really applies to any sort of game. How do you organize the game objects in a way that is structured, like the Model-View-Controller pattern? It looks to be an amazing pattern, very widely used and makes a lot of sense, but I'm having trouble figuring out how to implement it.





For instance, I need to keep track of a GL object for drawing to the screen. I have to have classes that implement MouseListener, MouseMotionListener, MouseWheelListener, and KeyListener (or one class, an all-in-one input manager). And I have to put my game data somewhere where all these different classes can access and modify it; if someone presses a button on the keyboard, the input managing class needs to somehow perform the action that the key is mapped to; when a frame needs to be drawn, the graphics class needs to find a way to loop through all the different 'things' and draw them all.





And my biggest issue, the GUI; where does it tie into it all? It's something like the input, but not quite, and it needs to both set and get pieces of data from the actual game simulation... And complicating it even MORE is if I decide to try and add networking, which (similar to the GUI) also needs to have access to a lot of the data for modifying and reading...





Oh, I'm just all confused. I don't know how to make all this work together in an object-oriented fashion... It's easy enough writing things that clearly fit the patterns, but when you have tons of things happening all tied to one game loop, modifying each other and the game data and so on, ... I don't even know any more. Maybe I'm just making this a bigger deal than it actually is.





Has anyone else felt this way? Please offer some clarity to my situation so I can spend less time worrying and not knowing where to start!





-Ricket





Edit: Found a nice diagram that might help me figure this all out... Source: (beware, PS file!) http://www.tucs.fi/publications/attachment.php?fname=TR553.ps.gz





http://img10.imageshack.us/img10/6278/mvcdiagramgamesbl5.png





Edit2: I also like this guy's explanation of how he planned his MVC game: http://interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc-game-development/





Edit3: Another great article! http://dewitters.koonsolo.com/gamemvc.html


Comments

  1. It might help you to think of the Model as a kind of game API. What would your game be reduced to if there were no UI at all for the game ordained from the beginning? You mention that what you have in mind is an RPG, so in this case you can imagine having the player character, his/her inventory, spells, abilities, NPCs, and even things like the map and combat rules all being part of the model. It is like the rules and pieces of Monopoly without the specifics of how the final game displays that or how the user is going to interact with it. It is like Quake as an abstract set of 3D objects moving through a level with things like intersection and collision calculated but no rendering, shadows, or sound effects.

    By putting all of those into the model the game itself is now UI agnostic. It could be hooked to an ASCII text interface like Rogue games have, or a command line UI akin to Zork, or a web based, or 3D UI. Some of those UIs might be a terrible fit depending upon the game mechanics, but they would all be possible.

    The View layer is the UI dependent layer. It reflects the specific choice of UI you went with and will be very much dedicated to that technology. It might be responsible for reading the state of the model and drawing it in 3D, ASCII, or images and HTML for a web page. It is also responsible for displaying any control mechanisms the player needs to use to interact with the game.

    The Controller layer is the glue between the two. It should never have any of the actual game logic in it, nor should it be responsible for driving the View layer. Instead it should translate actions taken in the View layer (clicking on buttons, clicking on areas of the screen, joystick actions, whatever) into actions taken on the model. For example, dropping an item, attacking an NPC, whatever. It is also responsible for gathering up data and doing any conversion or processing to make it easier for the View layer to display it.

    Now, the way I've described it above is as though there is a very distinct event sequence driving the game that is probably only really appropriate for a web game. That's because that's what I've spent my time on lately. In a game which is not driven by a user's request and a server's response like the web (e.g. a game running on the user's machine) you would probably want to make sure that the Model layer implemented the Observer pattern well. For example, if actions take place in the Model because time is passing then you might not want to have the View layer constantly polling the Model for updates. Instead by using the Observer pattern the Model could notify any observers of changes to Model objects as they happen. That could in turn be used to prompt immediate update to the View to reflect the change.

    Then if 60 seconds passing resulted in some repairs happening for the player's base, the base could effect the repairs and immediately notify any Observers attached to it that the base has updated. The View could be attached as an Observer and note that it needs to re-display the base because its state has changed. The notification itself might have included enough information to update the View or it might have to turn around and consult the model in order to update, but the result will be the same.

    ReplyDelete
  2. You're getting along there. basically, ask yourself the question "which code would change if I had to change some part of the program?"

    If it would change the way it looks without changing basic data, then it's in the view. If it is data that could be viewed in many ways, it's the model. And if it's how you play, then it's the control.

    So if it's whether you draw an "axe" with two blades or one, it's view. If it's how many hit points damage you inflict with an axe, it's model. And if it's whether you swing the axe by typing "s" or by right clicking, it's control.

    ReplyDelete
  3. I feel with you I remember when I first discovered MVC I tried to cram everything into it. I did indeed make a game that utilized MVC pattern. What I have found later though was that what I did was overkill. I tried to fit pretty much every single class I made into one category in MVC.

    What I suggest is to read "Design Patterns" by the gang of four. There are a lot of useful patterns besides MVC. Sometimes it doesn't make any sense to use MVC at all. Especially for games I am not sure if MVC is such a good idea. The reason being that you don't want to display a game object in many different ways (views), but you want to reuse a drawing code for many different types of game objects.

    For my own 2D game engine I used the strategy pattern quite actively. The game objects, like the player and the monsters I called a Sprite. I let the drawing of the sprite be handled by a strategy pattern. That is when I called sprite.draw() I would do something like this:

    class Sprite {
    void draw() {
    this.view.draw(this.currentPosition, this.currentOrientation);
    }

    Point currentPosition; // Current position of this sprite
    double currentOrientation; // Facing angle of sprite
    };


    The benefit of this approach is that you can share a view object between several sprites. Because typically there will be a lot of e.g. monsters which will look the same but which will be a different positions and possibly behave different.

    So behavior I would also use a strategy pattern which would be a object which contains code describing behavior. That way I can apply the same behavior to several monsters at different location. So each frame I would call an update() function to update position orientation and what monster does.

    class Sprite {
    void setUpdateAction(Action action) {
    this.updateAction = action;
    }

    void update(double start_time, double delta_time)
    {
    this.prevPosition = position();
    advance(delta_time); // Advance to next position based on current speed and orientation

    this.updateAction.execute(this, start_time, delta_time);
    }

    Action updateAction;
    };


    There are loads of variations of this. In my current implementation I have even separated out currentPosition, speed, orientation and advance() into a separate object called MotionState. This is so I can build a search trees of possible positions and orientations when doing path searching algorithms. Then I don't want to carry with me information about how to behave each update or how sprite should be drawn.

    ReplyDelete
  4. The MVC concept of centralizing user interaction logic is a good model for game development.

    I've done a little work with Flash game development. Here is an article about object pools in Flash. The concept is cross-platform and may give you some ideas.

    You're right to be concerned with all the stuff going on at one time. Depending on your game design, your game loop can have a lot to deal with. This is where you'll learn all the dirty optimization tricks, often the hard way :)

    There are many ways to organize your code- one option might be to write a GameManager class as a Singleton. All game objects tie back to it for management and user interaction. The GameManager handles all user input and dispatches messages to its object pool. You can use interfaces to define common communication patterns between game objects and the GameManager.

    As far as performance optimization goes, threading is very powerful. Asynchronous operation can ensure that you're not wasting those precious cycles.

    ReplyDelete
  5. All of your listeners and handlers need to go inside the Controller class, state of the objects on screen (e.g. position, color, etc.) should be a part of your Model classes and whatever code that is drawing things on screen will be part of the View.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex