Followers 0

# what's the C++/OOP way to implement this architecture ?

## 21 posts in this topic

what would be the C++/OOP way to implement this architecture ?

audio would play music and sound effects stored in the databases. it would be told what to play and when by the simulator.

input would get input from the keyboard, mouse, and other input devices, and send it to the simulator as needed/requested.

video would produce everything seen on the screen, as directed by the simulator. so it would include the renderer and gui components.

the databases would store all the game info. meshes, textures, materials, models, animations, sfx, music, the world map, the entities list, databases of entity types, object types, etc.  databases would be of 3 basic types: static databases would not change during one run of the game/level/mission. they would be read only - a database of target types for example. dynamic databases would be expected to change every frame. an entities list would be an example of this. semi-static databases might change, but usually not every frame. a list of dropped objects, or a changeable world map might be examples of this. other game specific databases might also be used. for example, CAVEMAN has action type and skill type databases.

the simulator would run the show. it would contain the main game loop. it would receive input and process it, updating databases as needed. it would perform all the update functions (IE run the game for one "frame" or "turn") or dispatch commands to the appropriate databases to update their contents. It would also dispatch commands and parameters to the audio and video units to do sound, music, and to render the screen. So its largely a controlling unit.

needless to say, this diagram is high level in the extreme, and each unit in it would in turn be composed of a number of sub units.

i'm pretty familiar with the non OO way this would be done, basically a bunch of adt APIs. but i was wondering what form a c++/oo implementation might take.

so before / while i start to slice this thing into classes and such, i thought i might get some suggestions from folks who do this everyday.

my natural approach would be to simply convert ADTs to classes. but i'm not sure if this would be considered the "usual" way to slice things or not.

for example, the entities list:

apparently in C++/OO, its common to implement an entities list as some sort of array or linked list of pointers to objects, where each object contains the info for one entity. furthermore, its also apparently common to create and destroy entity objects on the fly as needed.

in the non-OO world, this is a flat file database. a simple array of structs, nothing more. anyone who implemented an array of structs as a linked list of pointers to structs allocated on the heap would be thought to be "odd" at the least, if not "crazy".

so converting an entities list ADT to a C++/OO entities list in a straight forward manner, one would get and array of structs data structure with methods that operated on structs. the entire array would be one object. there would be an entitylist class, with a single instance, one entity list object.

but this doesn't seem to be the usual way its done in OO/C++.

i'm sure there are other places where this situation arises as well. I think it stems from the OO vs non-OO way of looking at data.  Apparently, in OO, it not uncommon to take "everything is an object" literally, and to the extreme. To the point where individual records in a database become objects, and perhaps even fields in those records. The result would/could/might be a proliferating tree of objects on the heap. Add in creating and destroying objects on the fly, and you have a constantly changing giant rats-nest tree of objects possibly/probably fragmenting the heap.

i'm thinking there's a way to slice things in an OO/C++ style with out the usual difficulties encountered, perhaps by using objects primarily as higher level modules / units.

Edited by Norman Barrows
1

##### Share on other sites
Wouldn't the simulator be the layer over the database and the Input, Audio, and Video would only interact with the simulator? As far as methodologies, I would think that MVC would be a contender.
0

##### Share on other sites

Wouldn't the simulator be the layer over the database and the Input, Audio, and Video would only interact with the simulator?

my original response was getting long winded, <g>  so i'll keep it short:

audio and video need access to the data to do their job. the simulator tells them what to do, but the data required to do it is in the database. so either the simulator gets all the data, then passes it all to the audio and video units (yuk!), or it just lets them do it themselves directly (sweet!) <g>. Think DMA transfer and microchannel architecture.

input doesn't really need access to the game's databases. it just gets queried by the simulator as needed.

As far as methodologies, I would think that MVC would be a contender.

model - view - controller.  hmm...  lemme wiki that to refresh my memory.

just looked it up.    its an architecture designed for business apps.   i'm not looking for a different architecture, i'm wondering how to implement this one in oo/c++.

the layout as presented may be too high level. i may need to specify the different part of the units (such as video), then ask for recommendations on implementations of those parts using oop/c++.

0

##### Share on other sites

There's a major difference between live data (in RAM, workable) and storage data. The concept of serialization is the bridge between the two things and I don't really suggest to even try doing it in a different manner.

Truth is even OOP is a buzzword. Yes, it gave us much more than many other methodologies, but don't take for granted it's the only thing in existance. When sending stuff over the wire (or to storage, for that matter) OOP does not hold much. You must send bits and will get bits, trying to convince yourself otherwise is trying to live in an abstract world. It's just numbers and conventions. The hardware will send you numbers, you will work with numbers. Period.

I think the main fallacy in your line of thinking is to draw a single "databases" block while there are clearly different databases involved. I strongly believe you didn't get the whole point of what OOP is, consider:

i'm sure there are other places where this situation arises as well. I think it stems from the OO vs non-OO way of looking at data.  Apparently, in OO, it not uncommon to take "everything is an object" literally, and to the extreme. To the point where individual records in a database become objects, and perhaps even fields in those records. The result would/could/might be a proliferating tree of objects on the heap. Add in creating and destroying objects on the fly, and you have a constantly changing giant rats-nest tree of objects possibly/probably fragmenting the heap.

The inference OOP-->objects on heap is wrong. OOP itself does not mandate heap usage, much less heavy usage fragmenting the heap.

The point is that you have "blobs" of data which you don't modify directly but use specific functions instead. In many OOP languages, the functions are "near" the data they manipulate. But they don't have to be! OOP is possible in C and even ASM.

1

##### Share on other sites
The diagram is so trivial and high level, containing only general categories of functionality, that even Krohm's criticism that there is only one "database" box is premature (the single "database" box means only "database-related stuff is layered below the simulator", without implying that databases are improperly consolidated into one Database component). I suggest, after thinking of your requirements, to start design from efficient and convenient algorithms and data structures; particularly in a very general purpose language like C++ you'll be able to fit classes to what your program really does, instead of hacking arbitrary class structures and inappropriate interfaces to make them behave acceptably.
0

##### Share on other sites

There's a major difference between live data (in RAM, workable) and storage data

it appears my diagram has caused confusion.

first let me fix that, (by posting a better one right quick) then i'll reply.

0

##### Share on other sites

hopefully this will be a little clearer.....

Edited by Norman Barrows
0

##### Share on other sites

There's a major difference between live data (in RAM, workable) and storage data

as you can see in the updated diagram.   the "databases" are only that data currently in ram or on the video card. not stuff on the hard drive, or received via network, etc.

sorry for the confusion!

a single "databases" block while there are clearly different databases involved

obviously - or at least i thought it was obvious. <g>.    lack of precision - my bad!

yes, the "game data" represents multiple data structures of different types, holding different types of data.

here's what the list might look like for CAVEMAN:

* a list of active players (like an entities list, but for multiple player characters).

* an entities list (vector, list, component-entity system, etc).

* a list of world objects (basically static entities like dropped inventory items)

* the world map data structure

* a list of known npc's and their data.

(  CAVEMAN generates npc's on the fly, so it only needs to track npc's you've met. a game like Oblivion would have a large "database" of NPC's, although the data might be split up between many levels or cells. in such a case, the equivalent would be the npc's active in the currently loaded level / cell / area. )

* entity type definitions

* object type definitions

* action type definitions

* skill type definitions

plus others that don't come to mind.

The point is that you have "blobs" of data which you don't modify directly but use specific functions instead. In many OOP languages, the functions are "near" the data they manipulate. But they don't have to be! OOP is possible in C and even ASM.

yes. this is what i do now. basically ADT's in C.

you'll be able to fit classes to what your program really does

over the years, i've noticed that what most games "really do" is something similar to the above diagram.

i suspect that the layout as presented is still too high level, and lacks sufficient detail to elicit responses on implementation recommendations for different parts.

i should probably take it one unit at at time.

i'll reformulate my question to be multiple specific implementation questions, instead of "so what would be some cool classes for this architecture?" <g>.

please stay tuned, as i was hoping you guys would chime in with some advise.

Edited by Norman Barrows
0

##### Share on other sites

In general, I follow an MVC or MVVM pattern for the general architecture. Whether the data lives in a flat file or in a database doesn't have much of a bearing on the design, other than choosing one, the other, or both from the get-go. It can be convenient to have a database (or multiple databases) since you can do queries and possibly even perform some logic in a stored procedure when its desirable (really, if you use a database, you should do this for any action which might leave the database in an inconsistent state if it were to fail mid-way, because the database can make sure the entire action is atomic -- that is, all or nothing).

Storing binary information (like audio or images) can get a little hinky unless its a fixed size shared in common with other files of its type -- You could, in alternative, combine flat-files with a database if you really want the ability to query over binary data (with associated metadata), by storing the files path in the database, rather than the data itself.

0

##### Share on other sites
I'm not really sure how you would accomplish what you think you're trying to accomplish here.

For instance for the audio you would have to retrieve the data from the database, even if database is just a buzzword of abstraction meaning a variety of long term storage the audio can't just "grab" it from the database. I'm assuming database just means "data" because getting audio from a database sounds like a terrible idea other than as a reference to where files are.

There's no "audio program" or something either, your simulator is going to get the data from somewhere and use the audio code to play it, what your chart shows is basically expecting data and a subsection of the simulator to work without the simulator actually doing it, and there being some performance difference with it, I really don't understand.

DMA transfer is not even remotely in the same category of what you're talking about because DMA transfer relies on hardware units, hardware may not be the CPU but it still has intelligent processing of data, it has the capacity to access other parts of the system and that isn't at all akin to your "audio and video units" it would always be a section of your user running code. Edited by Satharis
0

##### Share on other sites

The overbroad "Game data" in your new graph is still not very useful.

Have a look at the C4 Engine overview:

my diagram only covers the "system managers" and "large scale architecture" portions of the C4 diagram. "low level library" and "base services" are assumed, and not included in my diagram.

each unit in my diagram in turn would have a diagram of its parts. all those diagrams, plus the diagrams of the assumed low level stuff would add up to something similar to the C4 diagram.

obviously i need to provide additional lower level detail.

From your diagram, "input" generally does not directly send input to the simulator. Generally it gets converted into events and handled by the UI or by an object picker that navigates the scene structure, which in turn gets generated into more events that potentially get forwarded to various other systems and game objects for processing.  Those events are usually picked up by individual objects, not by the general simulator.

input is received. its converted to events. then i use an input handler to process the events and any additional events generated thereby. the input handler would be part of the simulator. the input unit would simply provide raw keystrokes, mouse actions, controller buttons, network packets, etc. network packets might be converted to keystroke or whatever first, as soon as they were received from a remote computer.

the diagram definitely needs more detail.      i'll improve it.

Audio is generally triggered by UI code, or (rarely) directly by game object code, or (most often) by animation events. Audio is best when kept in sync with animations, hence the strong link between audio and animation.

my "audio" unit is a low level playback module. the simulator would tell it what to do, and when. for example, the input handler would trigger weapon fire sfx when a "fire weapon" event was received as input.

but your point about having the animation player trigger footfalls is excellent.  exactly the kind of insights i was hoping to get by starting this thread.   thank you!

so that means there will need to be a connection either from the part of the simulator that controls the animation player, or from the animation player itself, to the audio unit. that is one link i overlooked.   but easily added.

It also has a connection to one or more resource caches

those would be the "audio data structures" in the "game data".  hence the link from "game data" to "audio".

Interconnection between systems is much more complex than your diagram demonstrates.

i'll work up a more detailed one.   thanks for the help so far!

0

##### Share on other sites

In general, I follow an MVC or MVVM pattern for the general architecture. Whether the data lives in a flat file or in a database doesn't have much of a bearing on the design, other than choosing one, the other, or both from the get-go.

over the years, i've discovered that perhaps as many as half of the major data structures in a game tend to be some sort of implementation of some type of relational database system.

a player "record" in the player "database" for CAVEMAN has links to the following databases: models, animations, animation players, textures, and entity types. one field in the player record is an entire inventory database.

the animation player record links to the model and animation databases.

the entity type record links to the model database.

an inventory item record links to the object types database.

an object type record links to the mesh and texture, or model and animation databases.

a model record links to the mesh, texture, and material databases.

Storing binary information (like audio or images) can get a little hinky unless its a fixed size shared in common with other files of its type

this is where i combine C and C++ syntax.    i'll usually use a static C array of COM object pointers, big enough to get the job done.   i use DirectX, and it stores audio, meshes, and textures as COM objects.

Edited by Norman Barrows
0

##### Share on other sites

DMA transfer is not even remotely in the same category of what you're talking about

the direct link to data was the part i was referring to, not the multi-processor part.    probably a bad analogy.    forget i mentioned it.

i'll work up a more detailed diagram.

i've already written a snippet of example code, so we have something concrete to work with. i'll post that for inspection, then start on a better diagram.

0

##### Share on other sites

I worked up this example code snippet as a test.

it implements a simple flat file read only database. I find this type of database to be very common in games. i use this type of data structure for meshes, textures, models, animations, materials, sfx, music loops, etc.

the code is generic in nature, and can be adapted to any appropriate data type, such as those listed above.

basically its just a straight translation from C to C++ syntax.

.

.


#define MAX_STRUCTS 10
struct my_struct                    // a "database record"
{
int data;    // representative data
LPDIRECT3DTEXTURE9 tex;   // use texture data as an example
};

class my_class                // a "database"
{
public:
my_struct list[MAX_STRUCTS];
int num_structs;

void load_struct(char *filename)        // load single mesh, tex, wav, etc from file
{
filename[0]=0;     // suppress compiler warning by using filename somehow
}

void load_structs(char *filename)       // load multiple meshs, texs, wavs, etc from a list contained in a file
{
filename[0]=0;     // suppress compiler warning by using filename somehow
}

};

void test2(int texID)     // test some syntax for setting a texture, and getting a value from the "database"
{
my_class a;
int b;
Zd3d_device_ptr->SetTexture(0,Ztex[texID].tex);            //     set texture, C version
Zd3d_device_ptr->SetTexture(0,a.list[texID].tex);          //     set texture, C++ version  (example call)
b=a.list[4].data;                                          //     get a value from the "database"
}



.

.

so, how bad does it look ? <g>

Edited by Norman Barrows
0

##### Share on other sites

ok, version 3 of the diagram.

data structures, low level libraries and services, and network output are omitted.  animation playback of audio is included.

details on the renderer unit are next.

0

##### Share on other sites

the renderer unit:

I've tried to make this as generic as possible, i will give concrete examples as well.

renderer unit API:

render all

the drawlist:

i use a data structure (a scene graph ?) that i call a "drawlist" to store a list of all the meshes to be drawn, sorted on texture.  the API consists basically of: clear, add, and draw.  it draws all meshes in the list in texture order, using a state manager.

render all:

set lights

set camera

clear drawlist

begin scene

render environment to drawlist

render objects to drawlist

draw drawlist

end scene

at this point, things start getting game specific.

render environment:

this will depend on the type of environment to be rendered. for an outdoor scene, it might consist of drawing the sky, the ground, rocks, vegetation, etc, and any man made objects like buildings. for an indoor scene its would consist of drawing the current level / cell / area based on camera location. caveman actually renders three types of environments: indoors, outdoors, and underground. rendering an outdoors environment in caveman consists of rendering a skybox or clearing the screen, then rendering the sun or moon, clouds, rain or snow, and the terrain (ground mesh, vegetation, rocks, etc ).  generally speaking, render environment will use the "world map" or "level map" and related data structure(s). caveman has a world map, four pattern maps for rocks and plants, and a database of caves, rock shelters, and huts. these are used to generate terrain chunks on the fly as needed for drawing (with LRU caching of course <g>).

render objects:

games tend to have lists of things.  lists of entities, lists of static objects, lists pf projectiles, particle lists, etc, etc.  so render objects is basically:

list1.renderall

list2.renderall

...

listN.renderall

where of course list.renderall is simply:   for each item in list, item.render.

item.render:

rather game specific. i'll give an example from caveman.

1. get basic drawing information (meshID, texureID, modelID, scale, primitive type [mesh / model / 2d billboard / 3d billboard ] ) from appropriate data structure (entities list, enemy type definitions, or object type definitions). entities, enemy definitions and object definitions all have basic drawing information in them.

2. set any additional variables necessary such as current position and rotation.

3. for human models: set skintone texture set used by the model

4. for animated models: set current animation frame for the model

5. add drawing info to the drawlist.

still, generally, speaking, a game will have basic "how to draw it" info for all objects in the game. it will then apply instance specific data such as location, orientation, animation frame, etc. then it will use all this info to actually draw something, using meshes, textures, models, and animations stored in data structures.

Edited by Norman Barrows
0

##### Share on other sites

As a side note, you might want to try out DoxyGen (eventually with some dummy code). It can do the graphing for you albeit it's fairly stupid in what decides to draw and what not IMHO. At a certain point it becomes just easier to write the code rather than trying hard at design.

Implementation brings you knowledge, which leads to good design. I think you should start writing something if you haven't already.

0

##### Share on other sites

I think you should start writing something if you haven't already.

well, lets see, i've done let's say a dozen, probably more, published games over the years. i'm guessing here. its like girls i've dated. each time i try to remember them all, i remember one i forgot the previous time i tried to remember them all!  <g>.

i got back into game development seriously for the 4th time about Jan 2012. since then, i've gotten a RTT game to alpha, a FPS/RPG to beta, and early prototypes of a flight sim, a city builder, and a RISK - type turn based strategy game going. I've also done  the de-regeur low level library for audio, graphics, timers, etc already.

recently i did a generic "entities list" library, sort of as an experiment - searching for patterns for use in games.  soon after, i re-designed it, and added a basic "game engine" framework. In parallel with this work on the entity list and game engine code, i've been revisiting the topic of using traditional c++/oo for games.  I actually used to make and sell game development libraries and tools, and have been considering  perhaps releasing some of Rockland's in-house libraries or writing some articles or journal entries, but most folks would probably want to see them with a c++ api.   i've been a fulltime indie since before C++ was invented. when it came along, it didn't offer that much for the single developer working on a single game project.  its was mostly about reuse of code in enterprise level development with large teams, etc (which AAA game development has practically become these days).   recently i thought i might give it another look-see.  however, despite it having been around for years now, there doesn't appear to be much consensus on how to write a game in c++.    i would have thought that by now someone would have figured it out, given the popularity of both C++/OO and computer games compared to back then.

the most recent thing i wrote was tonight. i took the combo game engine / entities list module, and made a new version that can be used as a stand alone library, without requiring any user defined callbacks, like the game engine version has. then i used this new version to rapid prototype a runtime module for a high level p-code game programming language virtual machine.  then i wrote a little 40 byte program in the language's virtual machine code that starts directx, loads all graphics and audio content, then goes into a loop where it clears the screen, displays the name of the programming language, displays the framerate, and checks for ESC being pressed. when ESC is pressed, it shuts down directx and quits.

so as you can see, recently I've been playing around with game architecture, game library, game engine, and game module design a bit - and now, dedicated game programming languages too.
Edited by Norman Barrows
0

##### Share on other sites

Going defensive much?

You don't need to.

I think you should start writing something (regarding this) if you haven't already.

-1

##### Share on other sites

Going defensive much?
You don't need to.
I think you should start writing something (regarding this) if you haven't already.

defensive, hardly!  guess i misunderstood.   writing code? or something like a blog entry?

that was just an example of the code i've written or am writing that i'm basing my observations on.

i already have pretty much all the bits and pieces for a "game engine architecture" sitting here on my hard drive, either in libraries, or as modules in game projects.   but the "gestalt" of the the design has yet to fully coalesce.

its like peering through an out-of focus telescope. at first the image is general and indistinct - like the first diagram.   what you're witnessing in this thread here is the slow focusing of the telescope to bring the design into clear, sharp view.

as usual, as with many of my "questions", the overall discussion is spread throughout a number of related threads, and spawned some interesting discussion.

i plan to cross link the threads for the convenience of all.

in this particular thread, at this particular time, the most helpful thing would be if someone could take a look at the snippet i posted, and tell me the c++ way to get rid of the global reference to texture[texID].

as an aside,  i had another interesting insight / discovery / pattern (dare i use the term?) that i noticed, similar t the link from animation player to audio:

you can't move a ground target in a generic game engine - even given all the 3d Newtonian kinematics data required - without game specific heightmap data to set the target's new "altitude" after moving. i discovered this while turning off callbacks in the library version of the target list / game engine.

perhaps a bit tangent to the topic, but: what does everyone out there think of callbacks? like? hate? necessary evil?

i've got the engine api down to two calls:

void Zmain(Hinstance);   and    void Zrungame();

and about a dozen callback routines, almost half of which are empty hooks for the user' convenience, and only the remaining ones actually require any user implementation.

0

## Create an account

Register a new account