Thread: Suggestions on early design

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218

    Suggestions on early design

    Hey guys! long time since i did anything of noteworthy here but anyway.

    Ive decided that I'm bored and i need a summer project, so what better than developing a graphics/game engine? I have done a very basic design of how i want it all to be ordered but figured I would run it past you guys before i get too deep into it. Last time i tried a major project i did not do any specific planning at all and i ended up scrapping it because it became one huge gigantic pile of mess. This time i want to do it right from the start.

    The design is located at: http://jopix.olf.sgsnet.se:8080/layout.png
    A little explanation of the arrows:
    A complete black line means containment, going top down: 1 CApplication will contain 1 CWindow

    Dotted line: Dependency, I think i used this one correct: i.e. CRenderer depends on CObjectHandler in that it needs to know about every object in the scene.

    Line with open triangle means inheritance.

    This is a very early design but as I said, I want it right from the start. The goal is to design it so it is easy to add or change stuff (ie, animated textures, animated models, shaders, scripted AI, or a completely new object with a completely different functionality but that still doesnt break it all) without massive rewrite of code so please come with feedback.
    Last edited by Shakti; 06-19-2010 at 06:54 AM.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    That doesn't look like the layout of a graphic engine or a game engine. It looks like the layout of a very specific instance of a poorly designed game or application.

    I'm not trying to be offensive. I just don't know how you go, with inheritance, from `CMovingObject' to `CModel'; why a `CTexture' isn't a `CRenderable'; why all of them need to inherit `CResource'; why `CResource' class has included manually written markup to provide context; why a `CMovingObject' doesn't reference other `CMovingObject' instances.

    Think about this use case for example (keeping the mechanic 2D for simplicity):

    You have a "character" (a sprite) with multiple potential active "powers" (overlay sprites). How can you manipulate the "powers" visual position without tracking them/updating them manually as you update the "character" position? You could create a `character' class to represent the "character" and a `power' class hierarchy to represent the "powers". However, a graphic engine has no business knowing details of game specific constructs like "character" or "power". Consider instead a single `ISprite' class (possible part of a hierarchy of graphic elements) implementing an `IPosition' and `IAnimation' interface which potentially contains, by reference, multiple `ISprite' instances with an "owner" relative position. The engine need not know the details, but you can manipulate the "character" directly and any "powers" directly or relative to the "character".

    I'm not suggestion you follow the above pattern. I'm just suggestion you look at graphic primitives and how they relate to each other in a game without bogging down the engine in game specific details.

    Soma

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    I go from CMovingObject to CModel through the fact that CMovingObject is inherited from CObject, which in turns consits of n CModel objects (no inheritance in that relationship, its a "has" relationship and not an "is" betwean those 2).

    CResource includes manually written markup for fail-checking when casting (possibly take this one out). CTexture isnt CRenderable because you dont render a texture, you use a texture on a face that you render (possibly) as a part of a bigger model.

    Now this I dont understand at all what you mean:
    why a `CMovingObject' doesn't reference other `CMovingObject' instances.

    the whole point of CResourceManager is that you load in everything used in a scene once to the resource manager. This manager will never contain the same thing twice, never, must not. And because of this I chose to inherit everything from CResource. CResourceManager will only serve as a sort of keeper of blueprints that are then later on used by CObjectHandler and so on to create the actual objects used in a game.

    To answer your example:

    I would would inherit a CPower class from CObject. Inherit a CPlayer class from CRenderable that contains a number of CPower objects (this part isnt visual in the design yet, CPlayer may or may not be an instance in CApplication), render the player, then that render function of player will set all positions for rendering of power objects, then call the render function of each power. Each object has to take care of its own rendering, and any child resources that needs to be rendered.

    I will certinly think about your interface-design suggestion.

    Edit: Thinking about it though, CModel should probably be inherited from CRenderable and not from CResource
    Last edited by Shakti; 06-19-2010 at 09:05 AM.

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    inherit CPower from CObject
    inherit CPlayer from CRenderable
    CPlayer contains a number of CPower
    the CPlayer render function will call the render function of each power
    How could it when you've just told me that `CPower' isn't a renderable object?

    What if `CPlayer' needs a companion? (a dog?) A companion isn't owned, is it? Or is it? Should `CCompanion' be contained? Should `CCompanion' be a free roaming agent? What about ambient powers that effect the environment but not the player directly? (a torch) Should the `CPlayer' contain environment effects since they are "owned" by the `CPlayer' instance? Should they be a distinct renderable object managed by the resource? What about natural environment effects? (rain) Should they be a unique entity contained by the application?

    You seem to be trying to lump a specific instance of "game" with "game engine" and "graphic engine". Consider a larger application of core utilities and you'll very likely develop much better code.

    Soma

  5. #5
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    CPower is renderable, it inherits from CObject which in turns inherits from CRenderable (or it might inherit from CRenderable directly if its not an in-game object per say).

    If a companion isnt owned its not so much a....well companion, now is it?
    CCompanion: CPlayer would hold an ID to a CCompanion, CCompanion in turn would be inherited from CRenderable (or possibly some other suitable class in that chain of inheritance, say a CAnimal class or something like that). We just tell the companion the players current position (and lets the companion figure out his own position based on that). The renderer then has to call the render function (probably makes more sense).

    A tourch would be something along the lines of: CPlayer holds tourch in hand, thus tourch is of type CObject. CPlayer knows of the object in the hand only through an ID that each object is assigned (and is used to look them up in the object-handler).

    I did place a CEnvironment class in under CRenderable, and yes IMO they should be managed by the resource-manager simply because you will probably load them from a file somehow and everything that gets loaded from a file gets managed by the resource-manager. I just dont have that in the design atm.

    The classes I have depicted in the picture are not all classes that would go into the system, they are not the final classes that would be there either. I simply posted here to discuss the concept of the layout.

    I just came to think of that no, a CPlayer class should not be responsible for rendering anything, since the player doesnt truly own anything. It only owns stuff with regards to that it has ID's to objects handled by an object-handler. It is only the renderer that can tell an object to render itself. So in my example with the powers the renderer would be the one to call the render function, while the player tells the power where it should render.

    Oh and just so you know: Im happy for all thoughts i can get
    Last edited by Shakti; 06-19-2010 at 10:19 AM.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    That doesn't look like the layout of a graphic engine or a game engine. It looks like the layout of a very specific instance of a poorly designed game or application.
    I'm not sure where you get this from since there are no game-specific entities defined in any of the design. What has been designed here is a generic framework from which to create middleware pieces that can then be used to implement specific game types. I also fail to see the 'poorness' of the design. Overall it is a good design save for a few areas where some ambiguity comes into play.

    As I said, I really don't see much wrong with the design other than where CRenderable is and the fact that since it is in it's early phases it is missing a lot of items. One key issue I see is with CRenderable. I would think of it as using resources instead of actually being a resource itself. Meshes, textures, sounds, shaders, etc. are all resources but renderables are more than likely going to be what is in your final render list. Not actually a resource per se.

    I also do not feel there is enough of a distinction between a moving object and a stationary object. Both will use a Frame class (an item which is missing from the design at this stage) and since the frame class would support orientation then position and so forth would already be handled. The physics system could then be plugged in to alter the frame of each object based on physical properties of that object and of the environment where the object is. The render system would then most likely parse the scene graph of the object (if needed), set render states, etc., and render the object based on the information contained in the graph. The root of the graph would be transformed into world space thus moving the entire object into the correct space.

    Some other systems that may be needed:
    • A texture manager
    • A mesh manager
    • A shader manager
    • A sound manager
    • An animation manager
    • A sprite manager
    • A render manager or render system
    • A 3D orientation system - complete with hierarchical transforms
    • A script manager


    If you want to make this cross-platform then you would need some foundational classes that abstract I/O, memory allocation, etc. Your current set of classes would then use these classes to perform the various I/O. Your various implementations of the I/O, memory allocation, etc. would either use Win32 or Linux or whatever platform your impl is targeted for.

    Now while you have a resource manager it is not clear by looking at the list which resources are textures, meshes, etc. Although they could all derive from the same interface your various managers could just as well derive from a common interface. This sort of eliminates the idea of a centralized resource manager althought the centralized version could just contain pointers to instances of the various managers you have in the system. I'm not sure you can lump every resource into a heterogenous list and support everything you would need for maintaining the resources.

    If you stick to this design though it is a good start and it is not hard-coded for D3D or OGL. Those don't come into play in the interface design and play a part later when you begin to implement this system on your target platform. I highly recommend two things:

    • Design your core interfaces prior to doing implementation
    • Do not use any implementation defined types in your interfaces
    • Do not use STL types in any interfaces
    Last edited by VirtualAce; 06-19-2010 at 02:55 PM.

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I'm not sure where you get this from since there are no game-specific entities defined in any of the design.
    I'd love to know where I said that there were any game specific entities.

    What has been designed here is a generic framework from which to create middleware pieces that can then be used to implement specific game types.
    No. It is not. I feel that that is what he wants, but that isn't what he has designed.

    I also fail to see the 'poorness' of the design.
    Then why did you reference the poor parts of the design?

    Overall it is a good design save for a few areas where some ambiguity comes into play.
    For thinking it is a good design, you sure referenced a lot of issues.



    I was trying to lead him to a better design by asking him questions to point out areas of interest he may have missed.

    You, on the other hand, are trying to cram the issues down his throat. Good luck with that.


    [Edit]
    Do not use STL types in any interfaces
    And as always, this is advice is complete crap. Spreading your misunderstanding of an ABI issue as a template issue is harmful to others.
    [/Edit]

    Soma
    Last edited by phantomotap; 06-19-2010 at 03:22 PM.

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    ...It looks like the layout of a very specific instance of a poorly designed game
    This communicates 'game' to me and yet there are no game-specific pieces in any of the design.

    Spreading your misunderstanding of an ABI issue as a template issue is harmful to others.
    It is not a misunderstanding and it is not harmful. STL versions are not always compatible with one another and code will crash if you pass a 2003 string to a 2008 DLL or vice versa. So unless you have a static build environment (which is not what DLLs were designed for) then this is valuable advice. You can pass a const char * from a 2003 DLL to a 2005 or 2008 or 2010 DLL that takes a std::string b/c the implicit conversion is done on the DLL side. However I invite you to try out the other option of passing a 2003 std::string to a DLL built in another version of the compiler and post your results.

    I'll revise my statement:
    * Do not use STL types in any external interfaces.

    Normally I agree with you phantomotap (man your name is hard to type) but on this one I guess I just agree to disagree. No hard feelings.

    A great thread on this issue:
    http://social.msdn.microsoft.com/For...a-340939218269
    Last edited by VirtualAce; 06-19-2010 at 04:14 PM.

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    *shrug*

    I don't really care if you agree or disagree. I also don't have an issue with you notifying people of compatibility issues when it comes to C++ compilers. What I have an issue with is that you never complete the information. You always only tell half the story. It is not a template issue. It is an ABI issue.

    You offered me the challenge of passing a `std::string' instance across module boundaries of an unfamiliar call frame or ABI? I don't have to try such a challenge. I know it will not work. I've been programming for over twenty years. I offer you this challenge. Compile the code I've included here and attempt to export it across module boundaries of an unfamiliar call frame or ABI. There is no template code here. There is no exceptions used here. It still will not work. It may work for any particular compiler or set of compilers, but you are still limiting the target consumers to a specific set of tools. This is the nature of C++.

    The way C++ compilers pass the `this' pointer to methods, the way C++ compilers store the virtual table pointers, the way C++ compilers mangle names, all of it varies not just between different compilers, different versions of the same compilers, different versions of the relevant linker, different versions of the libraries, different versions of the headers, different defines used when building the libraries, but even with compiler options that may seem trivial when passed during building or linking the primary executable or shared library.

    If you are worried about a shared library being useful across different versions of a C++ compiler (the primary scenario you usual reference) you must not export ANY C++ entity whether or not the source uses templates.

    If you are going to export any C++ entity as part of the interface for public consumption, you may as well export templates and exceptions as well if your target compiler supports it because the other C++ entities you may wish to export are also tied to the particulars of a build.

    Soma

    Code:
    class base
    {
       virtual void go();
    };
    
    class d1: public base
    {
       virtual void go()
       {
          std::cout << "d1" << '\n';
       }
    };
    
    class d2: public base
    {
       virtual void go()
       {
          std::cout << "d2" << '\n';
       }
    };

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you are worried about a shared library being useful across different versions of a C++ compiler (the primary scenario you usual reference) you must not export ANY C++ entity whether or not the source uses templates.
    Yep, this is true.

    I see that your problem with my statements is that I'm not telling the entire story. Understandable. I know you are quite experienced and would never question that which is why I was surprised when I thought you were saying my advice was incorrect. I did not realize that your beef was that I didn't tell the rest of the story. My posts about this are long enough already without adding more and more stuff to them which is why I normally stick to the issue at hand when possible.

    However, my apologies for the misunderstanding. I definitely respect your opinion and was a bit shocked that you and I had a bit of a falling out here. Let's call this one done shall we?
    Last edited by VirtualAce; 06-19-2010 at 07:05 PM.

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Sure.

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Game Engine Design
    By IceDane in forum Game Programming
    Replies: 2
    Last Post: 01-17-2010, 02:47 PM
  2. Design suggestions: interacting with game items
    By anon in forum C++ Programming
    Replies: 3
    Last Post: 09-19-2008, 08:03 AM
  3. which design is better to wrap another class instance
    By George2 in forum C++ Programming
    Replies: 7
    Last Post: 04-13-2008, 12:27 AM
  4. Implementing Inheritence into your design
    By bobthebullet990 in forum C++ Programming
    Replies: 6
    Last Post: 08-05-2006, 04:40 PM