About separating game logic from rendering

Hey guys, I’m new to game development. Anyway, I was reading stuff on how you’re supposed to completely separate game logic from rendering. So does that mean you shouldn’t use logic statements at all during the rendering portion of the code to determine whether to draw an object or not?

for example:

gameloop(){
     //Update
     stateTime += delta time;
     movementInput();
     if(player is at a certain position)
        atPosition = true;

     //Render
     if(stateTime > 5 && atPosition)
        draw(something);
     else 
        draw(someOtherThing);
}

If so, what’s a better way of controlling which things to draw to the screen?

It means that ideally you should be able to express your code something like this:


gameLoop:
    processUserInput()     // kind of separate from game logic, but could include in processGameLogic
    processGameLogic()     // produces the current game state from last frame's state
    renderCurrentState()   // does nothing to change game state, only renders it
    sleep(remainingTime)

The game state doesn’t have to be a single object (although it could be), it is comprised of whatever datastructures you use to store e.g. the currently loaded level, it’s map, the entity list, the player’s position, inventory, score, etc.

Rendering of course can (and probably will, depending on how you define it) use ‘logic’ during it’s step, but that program logic should be separate in that it has no effect on what the current game state is. It is local to and contained by the rendering phase. render()'s only job is to read and display the state.

User input can/should also be it’s own step, which can be a sub-step in the logic phase if you like, I described a single method using queues here:

[quote=“cuprite,post:1,topic:55355”]
No.

The “you should separate game logic and rendering” rule might be better restated as “your rendering code should not change your game state” instead.

It’s completely fine (and expected) to poll your game logic (determining player position, etc) from your rendering code. But your game’s model should be able to run completely independently of the renderer.

In other words, I should be able to write a renderer for your game, and I should be able to swap it in to your code with a one-line change (call my renderer instead of yours) without requiring any changes to the underlying game model.

This becomes useful for porting your game over to multiple systems. Oftentimes your game model will remain mostly the same, but only your rendering code will change. If you keep the two separate, that becomes pretty easy.

Take into consideration that this should be considered a guideline, not a holy grail. When you develop your game, you will most likely suck at it at some level, and the code will be a complete mess. This is okay, as long as you learned something developing these small games. People who get stuff done, tend to be less uncomfortable with crappy code.

So don’t start refactoring just yet - developing and finishing a game is - at this point - the goal. Keep general guidelines in mind, but by all means don’t try to make the renderer swappable. Such things are incredibly hard for developers with a decade of experience under their belt. Ask yourself this: will you port your game to another platform any time soon? If not, don’t bother, just get your game playable, that is hard enough as it is, when you’re new to the game.

I absolutely agree with Riven: especially if you’re just starting out, any code you write is going to seem terrible in 6 months. This is a sign that you’re improving. But it also means that spending a lot of time trying to refactor your code to be perfect gives you vastly diminished returns as compared to just finishing something that works and moving on to the next project.

It’s nice to keep in mind the general guidelines of game development while you work, but I wouldn’t become overly worried about strictly adhering to them. They’ll become more natural to you over time.

Making the rendering code swappable is an interesting idea, nice one KevinWorkman.
But then in some respects, keeping the render method as a part of the game object being rendered also has an elegance to it. After all, the game object would know best how it should be rendered and any refactoring or improvement made to the game object state can be easily updated in the rendering code in that game object class, rather than finding the renderer class and updating it there.

Reminds me of argument over using classes versus entity component systems like artemis.

Thanks. To be fair it’s not really my idea, it’s just the application of MVC logic to game development. Your model shouldn’t care about your view or controller, to the point that you should be able to swap out your view and controller and have your model still function.

In my experience, the ability to swap out your view/renderer is more of a “best case scenario” goal to shoot for than it is something that actually happens very often. Most people probably don’t care about literally being able to swap out a renderer, but separating your code as if you did care about it will make your life easier in other departments as well.

[quote=“CommanderKeith,post:6,topic:55355”]
I agree, and that’s how I code my own games. That being said, I generally do keep my model code in a step() function, and then my render code in a draw() function. It wouldn’t be too hard to move my draw() function to a rendering class, and then swap out different rendering classes. If you keep your rendering code separate from your modeling code like that, you’re still semantically obeying the guideline of swappability.

[quote=“KevinWorkman,post:7,topic:55355”]

Yes i do the same thing too. The alternative entity component system approach is interesting and it would be nice to try it one day.

Thanks for all the replies! Ridiculously helpful!

Wise words from Riven. When you get your hands dirty, you have to compromise. Sometimes as he mentions, it is a matter of choosing between refactoring to perfection, or actually finishing the damn thing. And sometimes it is “intentional” bad design because of optimization, making your code uglier and less structured, but more efficient. In the end, coding is a means, not an end. The end is, your game finished, working and published.

Actually, when you mix the game logic with the rendering, there is no way to update the former less often than the latter. Do you really need to check if there are some collisions 60 times per second? Imagine that the end user disables the v-sync, should your game really run those checks as much time as possible? A physics engine can create lots of short-lived objects, running it only when it is necessary can be helpful to reduce the memory and CPU footprint of your game, especially on machines with a limited autonomy (laptops, mobile phones, …).

It depends on the kind of game that you create but maybe you’ll need to avoid mixing together not only to ease the port to other platforms. In my humble opinion, writing dirty code is a bad idea on long term projects (working with it will become increasingly discouraging as time goes by) and writing an independent renderer can be helpful if you need to switch to another library.

If you use a “good” framework or a “good” engine, you don’t have to worry about it as this separation is already done, just don’t mix everything in your own code.

Regardless of the specific domain of an application (game or something else), whether design is bad or not is determined by how and in which ways you see the need for change in the future and how well that change can be realized while still satisfying all functional and non-functional (performance, memory-footprint, etc.) requirements of the application.

If you see change in trying to port to another platform: Well, then you’ve got to have a design that supports that.
If you see change in trying to use another renderer (Direct3D?): Well, then you know what your design ought to support.

In the classic IEEE article “Who Needs An Architect”, written by Martin Fowler, Ralph Johnson was cited with, that it is simple to make one thing easy to change in a software system. But we cannot make everything easy to change, as that would make the whole system very complex.
So, yes, it is always about compromises and architecture is really just the design decisions that make further anticipated changes easy to do.

There is also no such thing as “good” or “bad” design per se. Sure, there are loads of books about basic design principles out there. But those are meant to help design your application in a way that it is easier to adapt to common and recurring changes.

But in my opinion, the “quality” measure of design is defined by how well that design supports anticipated change.
You can write the crappiest code for an application/game; if the application/game works, and given it will never change again, it was by definition not bad design.

Design always “becomes” bad when you see change that is not easy to incorporate.