0
\$\begingroup\$

For a game that I'm working on, we've followed the MVC paradigm. However, in classic MVC, the view subscribes to the model and when the model updates it informs the view. We've implemented this as an Observer pattern so the model doesn't really have a direct link to the view, to reduce coupling.

Now, given such a configuration, is the call to render in the game loop really necessary?

That is,

while(true){
 update(); //mostly called via user interaction
 render(); //necessary if called by model?
}

The game loop is more like:

while (game_is_running){
 getUserInput();//This updates models which in turn asks views to render the changes.
}

Is there really an advantage to having render in the game loop? Is it acceptable to have the models inform the view to render themselves? What's the preferred way to go about this?

\$\endgroup\$
  • \$\begingroup\$ It is good practice to have a loop with a complete set of the steps that are on a same level of sophistication. This provides the reader with a high level overview at a first glance. Putting part of that set elsewhere is like hiding them from the reader. So has to search for them or needs additional explanation. \$\endgroup\$ – FWE Jan 8 '15 at 10:37
  • \$\begingroup\$ Is this a turn based game? Does the game just sit still until input is provided? Does getUserInput receive null when the user does nothing? What happens inside getUserInput, can the rendering function fire off multiple times each frames because there are many changes? \$\endgroup\$ – wolfdawn Jan 9 '15 at 19:22
4
\$\begingroup\$

It's not necessary, in the sense that you can make it work. But your approach is somewhat... awkward.

In your approach, the pre-render and post-render work (such as clearing the appropriate render targets, and then presenting the final frame the screen) has to be done before and after getUserInput():

while (game_is_running){
  prepareForRender();
  getUserInput();
  completeRender()
}

After all, that work has to happen at some point and your only other approach here is to track whether or not you've started it yet and then make the views that happen to be the first and last to draw make the appropriate calls. This is ugly.

So ultimately in this approach you have one giant conflated frame that includes both input processing, logic updates, and render commands in an unstructured order. This is both hard to follow, hard to profile, and potentially extremely problematic as the complexity of your rendering increases (for example, if you don't have an order-independent transparency implementation you have to sort transparent things back-to-front and make sure they render in that order to get correct transparency; how is that bulk operation done in response to individual model updates?).

It also raises some serious questions about the viability of the approach under concurrency scenarios.

I wouldn't advise this approach at all. If you really want to adhere that closely to the MVC pattern, I'd make the "rendering" that your views do in response to model updates simply be the preparation of any bookkeeping that needs to eventually be consumed by the renderer when you later call render(). Things like making sure any visually-impacting properties that changes (like a unit going to a "critical health" state) are reflected in the data the renderer will eventually consume (like the "tint" color for that particular unit's shader).

\$\endgroup\$
1
\$\begingroup\$

Lets call everything that happens inside a game an event for the duration of this answer. The events that occur in a game are not "observing" the game model. They happen every x frames.

Rendering for instance happens every frame and the view doesn't need to care if the model changed or not since the previous frame. It normally will render every frame. This is not a utility type thing where you possibly don't need to render if no changes happened. This is a game, a resource hungry piece of software that uses every bit of power the computer can offer normally.

The model doesn't need to wait for input to change. The model is constantly changing because time is passing by. It could be creatures moving around or simply a clock that is ticking down.

The reason the thought process is wrong when using Observers to render a game is that rendering happens each and every frame. The game model is updated every frame. You check for input every frame. Games respond because input changes the state of the game but they continue to tick and take action when no input is given.

You need to think about the tasks the game may need to do:

 // Input
 1. Accept input from the users' peripherals.

 // Model state changes
 2. Comprehend the input and convert it into game commands or state changes.
 3. Compute movement, collisions, physics.
 4. AI.

 // Output
 5. Play sounds.
 6. Rendering.

 // Networking
 7. Communicate with the server or peers.

The models are important but all the processes will likely need to be handled every frame. If so then why trigger them with an observer? Why connect them conceptually to input? Why mix all the different types on manipulations that are done on the model with one another?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.