Video Game Architecture

Started by
26 comments, last by rocklobster 12 years ago
I am curently having a problem deciding on a broad scope how my game engine will be structured. One important thing that i am looking for is separation of logic and rendering. In order to do this my first idea was to to have a Engine base class and have two composited classes, Logic and Graphics. This all works until i try and implement a state system. I do not like the common state systems that are allowed a single state and use switch cases to decide what to do, so i got the idea of a Screen or Canvas class to encapsulate the rendering of a certain screen along with screen logic. The problem with that is that logic is now under Graphics:
[attachment=7934:diagram1.png]
Is there a more elegent/flexible way to implement a Frame or Screen type class that has the ability to handle its own state without having to mix rendering and logic? Would it be fine to implement the array of screens in the Engine and call their logic and Rendering separate?

The other thing i am curious about is, where is it that most game engines store the bulk of game data? In my game i was planning to put the game date in the engine class so all subclasses can be passed a pointer to the game data. Is this the most efficient way of doing this? I have heard quite often that most games use singleton instances for subsystems, is this the best way to declare subsystems and is this the best place to store a game data manager class?

Thanyou for your time
-Ryan
Advertisement
In my initialization, I create an instance of each subsystem which are all owned by the Game object. I also have a State class, and instantiate a State object for each game state I want. The Game object is passed to the State objects in the constructor, and can be queried for needed subsystem interfaces. Each state owns it's own game entities, pushes the ones that need updating to the logic subsystem during Update() and those that need to be drawn to the Graphics subsystem in Draw().

Ideally, the logic system will call lua scripts instead of having hardcoded routines. And I haven't yet implemented Begin() and End() methods for my State class to better handle state changes. But those are the plans.

I hope that gives you some ideas.

Edit: I don't use singletons. I instantiate a Game object, which owns the various subsystem and state objects. The Game object serves as a Service Locator so the states can acquire an interface to the subsystems as needed. In my game loop, I call current_state->Do(), and check to see if I need to change state. The game is small enough that I create each state once at startup, because each one is it's own scene and I didn't want to load/unload a (minimal) level whenever the player opens up the options menu. But I could theoretically create and destroy state objects dynamically as needed.
My game is set up similar, i have all my subsystems under the Engine class. You say that your state objects hold all data for a given state and hand the objects to the logic system and Render sysyem every frame? does this mean that your calling a State.logic() and State.Render() call every frame?

-Ryan

Edit: just read your edit and that clarified things a bit, this system seems very similar to my Screen system with screens being under Engine instead of Rendering, Thanks for the help :)

You say that your state objects hold all data for a given state and hand the objects to the logic system and Render sysyem every frame? does this mean that your calling a State.logic() and State.Render() call every frame?

Yes. In Do(dt) The State object compiles a list of entities with a Logic component, and pushes it to the logic system. Right now, the logic system doesn't do much more than call each entity's Update(dt), but I intend to have the logic component specify a Lua script for the logic system to call. Similarly, the State object compiles a list of entities with a Renderable component and pushes it to the Graphics system, which acquires handles to the various resources needed to draw the entities, batches them, and then calls Renderer::Draw() for each batch. A lot of the hatching process is specific to the game, so it's nowhere near as nicely generalized as it sounds. But I'm working on getting it there.
The same screenshot I posted in another topic may help.
[attachment=7939:EngineOrg.png]

I have 15 modules/libraries. The way in which things depend on other things is entirely logical.

At the bottom you have LSStandardLib. It provides a lot of macros for general use by the entire engine and all other modules, including LSE_CALL, LSE_INLINE, LSE_WINDOWS, LSE_APPLE, etc.
Additionally it provides general-purpose functions such as CStd::StrLen(), etc. These functions can usually be optimized beyond what you will find in the standard C library, but you don’t have to do it.
It also provides CTime, CLargeInteger, CSearch, CCrc, and a few other general-purpose classes that rely on nothing else. It is the lowest level in the engine.


Just above that you have LSMathLib and LSThreadLib.

Next up is LSMemLib. My memory manager. It relies on threads and CStd.

Next up is LSTL, which is my game-oriented replacement for the STL, and it relies on memory allocation. You don’t really need to do this probably, but if you do it would be here.

Next up are LSCompressionLib, LSFileLib, LSNetLib, and LSPhysicsLib. These rely on standard macros/functions, memory allocations, templates, file access, math, etc.

Next is LSImageLib. Textures may use these, but this class has no idea what a texture is. It knows what an image is and how to manipulate and load them. The reason it is not on the next level down is because it relies on LSCompressionLib and LSFileLib.

Next is LSGraphicsLib. It relies on LSImageLib for use with textures.

Next is LSModelLib and LSTerrainLib. They need to render themselves, so they need to know what a renderer is.

Finally LSEngine needs to know what everything in the engine is and how they should be connected. It is obviously at the top.


For ideas on how to manage states and the data in each state, you can read my article about it.
http://lspiroengine.com/?p=351


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This diagram of the C4 Engine architecture might interest you:

http://www.terathon.com/c4engine/architecture.php

This diagram of the C4 Engine architecture might interest you:

http://www.terathon....rchitecture.php


Jesus, that looks like mess.

I used a mix of MVC and three-tier for my engine and it works great. I tweaked it slightly so that the logic is torn out from the controller into its own tier.
Here is some background information, hope that helps:
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
http://en.wikipedia.org/wiki/Multitier_architecture

Jesus, that looks like mess.

What exactly are you expecting from a fairly complex engine?
And where exactly do you think your own engine is headed with just a modified MVC/three-tier system? You might want to think about that.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


What exactly are you expecting from a fairly complex engine?

I was expected a more visisble structure/code organization, also a decent level of abstraction in something like class diagram, so that you don't 100 classes thrown in your face.
Also, when looking at an architecture, I expect to see some thought behind the design, things I can identify as isolated packages with a purpose. I don't see that in the c4 architecture, just a bunch of managers with arrows all over the place.


And where exactly do you think your own engine is headed with just a modified MVC/three-tier system? You might want to think about that.

Well, with my engine, I am heading towards a tight integration of the game design document and the game code. The modified three tier system is just the way I organize the code, keeping the data, logic and graphics separated.


Also, having a complex system is no excuse for it being an architectural mess. There are tons of faults in the C4Engine class diagram, even if the guys at terathon software seems to be good programmers, they don't have a clue about software engineering.

[quote name='YogurtEmperor' timestamp='1333247123' post='4927083']
What exactly are you expecting from a fairly complex engine?

I was expected a more visisble structure/code organization, also a decent level of abstraction in something like class diagram, so that you don't 100 classes thrown in your face.


And where exactly do you think your own engine is headed with just a modified MVC/three-tier system? You might want to think about that.

Well, with my engine, I am heading towards a tight integration of the game design document and the game code. The modified three tier system is just the way I organize the code, keeping the data, logic and graphics separated.



L. Spiro
[/quote]

This topic is closed to new replies.

Advertisement