Jump to content
  • Advertisement

hyyou

Member
  • Content Count

    59
  • Joined

  • Last visited

Everything posted by hyyou

  1. I have many game system, e.g. System_Projectile System_AI System_Physics ---------------------------------------------------------------------------------------------- Sometimes, they have to call each other, so I provide a hub class.    Every game system derived from the Hub. public Hub{     template<class SystemX> SystemX* sys(){            .... return a pointer to singleton-instance of the system.     } } ---------------------------------------------------------------------------------------------- Therefore, I can call each system like this :- class System_AI : public Hub{     public: void update(){           system<System_Projectile>()->changeTargetToPlayer( ... something ... );     } } ---------------------------------------------------------------------------------------------- I think it is too long so I shorten the function and class name to :- s<S_Projectile>()->changeTargetToPlayer( ... something ... ); ---------------------------------------------------------------------------------------------- As the code become bigger, I have typed s<S_>()-> for a half year. ... /* many be many thousand times already.  */ Now, I am a master of typing the phrase s<S_>()->.                      ... /* a personal perk that I never wish for.       */ Question:  The code currently works well, but how to make it shorter?       Is it possible?    I am considering this below choice, but I have to manually create each field for each system.  Thus, it is not so robust. s_projectile->changeTargetToPlayer( ... something ... ); Furthermore, I can't call a system by the class name anymore.  (Thus, I can't directly "ctrl+space" like the above version.)
  2. Thank a lot, frob!   This is not the first time you help me.  :)   About "I can't call a system by the class name anymore" I meant that ...   I guess phil_t recommended like this :- class SystemB{     SystemA* systemA; public: void update(){ systemA->doSomething(); } }; --- Disadvantage:-   1. When I press ctrl+click at systemB in IDE,  I will jump to the declation of the field, instead of the class systemB.    Thus navigation across different parts of code become slightly slower.   2. I want to easily copy-and-paste code between different System. It is currently very easily. The below code can be magically copy-and-paste, it will work in every system! system<SystemA>->doSomething(); --- But with the proposed approach (use a field systemA) :- systemA->doSomething(); --- I have to maintain the name systemA to match all related system. class SystemB{     SystemA* systemA; }; class SystemC{     SystemA* systemA; //have to match the same name }; ---- About noun->verb()   It is an entity-based-component system, so I can't call noun->verb(). I usually call system<SystemName>()->verb(noun) instead.     I agree that it is less readable, but I don't know a better way.     About the ugly long name   I want help from context clue. For example, if I want to type:- system<System_AI>()-> I can just type a partial sentence, then context clue will pop-up all existing system in my project :- system<System_ It is so convenient!   Please criticize me more.  Thank.
  3. @phil_t I don't think Singleton is bad in this case.  (I know that it is usually bad.)   - A game system are like unity script / game maker manager.    (there is actually only 1 instance) - So far, I don't have dependency issue, because I can #include only I need in .cpp - In my code in the question, each system can call each other easily (A call B and B call A). - If only I design like Sys_AI::getSingleton() that would be a problem, I guess. - I have ever used the old approach (manual pointer), it caused some maintainability issue.   Am I wrong?  .... Thank for reply XD
  4. I have a entity-component-based game engine.   There are many systems, e.g. System_A, System_B ,... all derived from SystemDefault. If I want to use custom memory allocator, how can I used it in a real game?     Question 1: Where is the field "allocator", how many of them? Solution 1A :  Store it in a top header.   There might be 3 types: stack, one frame, and heap. Disadvantage: Many systems will tend to use the share allocator, thus this solution may not give much advantage about cache coherence.   Solution 1B :  Store it in each and every System.  (1-3 allocator per System) The most appropriate way for a big game is adding a field "memory pool" for SystemDefault. Disadvantage: Not all memory-allocation demand is in System_xxx.  For example :- Some AI or physic engines use its own architecture that is not component-entity.     Some custom datastructure may contain another small datastructure. For these cases, how should allocator be passed? Solution 1C : Store it in each and every "Allocator holder" Make every class that want to allocate some memory derived from a certain class AllocatorHolder. Disadvantage: crazy?   Question 2: How to enforce a code to use a certain allocator? Solution 2A : Use allocator of the system that contains the code. Disadvantage: There is a call like :-   //System_A  or System_B fA() or fB(){     loop{           array=System_C::doSomething();     } }   I don't think it is good - System_C::doSomething should use allocator of A, and B for each situation.  (right?) That is C should aware what class is using it - not just blindly use its own C allocator.   Solution 2B : Passing allocator when calling every function. Disadvantage:  The call will be :-   //System_A  or System_B fA() or fB(){     loop{           array=System_C::doSomething(this);  //or this->stack_allocator or this->oneFrame_allocator, etc.     }          } Now, every function practically should have allocator as a parameter - ugly.   Question 3: How to initialize datastructure? In my old code it is easy like this:- //inside SystemA     fA(){          MyArray<T> ts;     } Should I make it more harder like :-     fA(){          MyArray<T> ts; ts.setAllocator(this->stackAllocator); //applicable for 1A 1B 1C     } or ...     fA(){          MyArray<T,STACK_ALLOCATOR> ts; //applicable only for 1C     } ------------------------------------------------------   There are a lot of memory pool resources in the internet, but none mention how to use it in practice. Here is what I read:- Are we out of memory?                  (a popular article) C++: Custom memory allocation    (very long, provide usable code) How do you manually manage memory-allocation in your game? Are there any good books about this?  (which show more than the pool code + trivial usage)
  5. Thank a lot, frob.   It may be just my fear after read some memory-pool articles.           1. In many parts of my code, I allocate temporary MyArray<T> (and similar things) as information used to communicate between a pair of system.   These information are mostly deleted in one frame, but I can't guarantee it.      2. In some components, there is MyArray<T> as a field, so there might be some cache miss, e.g. class ComponentA{ MyArray<DataB> aFieldArray; } I am scared that memory will be fragmented because of two causes above, so I think memory pool is the solution.        I don't want to wait until the problem appear on surface, because refactoring might become very hard later.      I don't even know how the well-written game call the allocator in practice, so I can't evaluate how hard it is to refactor my code later.
  6. hyyou

    SDL Game Programming in C

    Why did you decide to use C instead of C++?   (just want to know)
  7. I have written a game library using Component-based architecture, including Ogre 2.1 and Bullet.   In the last few month, I created some tiny game as a prototype, and the library looks good so far.   Now, I started to create a more complex game.    Many features of my game start to work good within my game engine environment - but is a crap elsewhere.     Example   I have a custom data-structure - 3D grid manager, named Grid. class Grid{     GridMember* gridMembers;     int numX,numY,numZ;     void add (GridMember* gridMember, int x,int y,int z){           gridMembers[ ((z*numY)+y)*numX] = gridMember ;     }     //other functions }; - In the game logic, I used inheritance:- Game entity that stores  : derived from Grid Game entity to be stored : derived from GridMember - I found that this Grid class doesn't go well with the component-based architecture :-          The game entity should not have any function!!   So I changed it to match the component-based architecture. class Grid_System : Game_Engine_System{     void add (ID grid, ID gridMember, int x,int y,int z){.....}     //.............. other functions ............ }; Notice that Grid will now really depend on the game-engine.   ----------------------------------------------------------------------------------------------------------------------------   The fear about losing modularity in code start to overcome me.    It accompanies by fear that Component-based architecture will become an obsolete technology soon.   I have not slept well. I start to have nightmare in some nights. Am I worry too much?    
  8.   May you provide the more elegant signature of the function, as an example, please?  I am curious. :D   Thank, Tangletail too!       Yes,  grid square <--> object .   In real usage, the array is usually quite tight.  (I think I know what you mean. :D)   The object inside a grid is "game object". The game object should be stored as ID (entity) to make it still transparent to other systems. Therefore, grid should has ID as type of parameter.   I think this kind of binding is quite unavoidable.   Please fix me if I am wrong. :D
  9. Thank a lot, LandonJerre.   Now tonight, I can start to sleep well.  :D
  10. hyyou

    Becoming An Indie Game Developer

    I have created a game library with C++ alone, and I am quite satisfied with the result.   My step in the last few years :-   1. Learn Opengl from NeHe -> glsl  -> try to create a minimal defered shader engine 2. Learn Box2D -> try to create a small library that support a compound with constraint & custom collision callback 3. Merge them altogether -> create tiny library that bind physic & graphic together 4. delete all of them (Because I used Java.  Java is too slow.) 5. Learn Ogre3D (C++) -> encapsulate it  (Shader, GLSL, Mesh Loader, Transparent, etc.) 6. Learn Bullet -> encapsulate it  (Rigid & constraint & filter callback & collision callback) 7. Bind 5 & 6. together -> test 8. delete all of them ( bad design, because low experience ) 9. Learn software architecture e.g. component based 10. rewrite all of them again, now plan with a paper & pencil before write the real code 11. Learn more about C++ 12. re-architecture the result from 10.   That is a really hard work.   I almost quit many times.  
  11. I am under an impression that std::async and std::mutex can solve every basic-to-intermediate problem for multi-threading.   The multi-threading (in this scope) is to   1. increase performance of multi-core (to use all CPU-core) 2. avoid CPU stall e.g. L2 cache miss, especially when execute a ton of indirection (a->b->c->d)   Here is an example :-    std::vector<std::future> v;    v.push_back(std::async( &A::doThis, pointerToAInstance  ));    v.push_back(std::async( &B::doThis, pointerToBInstance  ));    v.get(0).wait();    v.get(1).wait(); This can be easily applied to a scenario that I have a long array of objects that need to be expensively processed.   If I want to split jobs again and again, I can std::async within std::async within std::async ...... look nice.   By the way, I heard that OpenMP is a popular library for multicore programming (https://en.wikipedia.org/wiki/OpenMP). However, as I am researching, I also found that most of its feature can be replaced by simplier std::async and std::mutex. OpenMP is a heavy weight library that just provides syntactic sugar, right?   I feel that I missed something.   Edit   @Josh Petrie and @SeanMiddledtich , thank for useful information.   Here is my specific experiment :-   My specific application is:-   I created my component-based-architecture game-engine.   I have little experience in multi-threading, but the architecture tend to support it inherently - it divided jobs into many systems (about 13 systems). Each and every system manages and accesses at most 2-3 components. (whole game = 20 components)  Therefore, most of systems can be executed in parallel.   Step 1   After I learned a bit of std::async and std::mutex, I use these two functions to make it parallel. I created std::future from each system, then wait() at the end of each timestep.   The modification is very conservative and highly-aware of concurrent modification and the order of execution, e.g. physic cannot be grouped with graphic. Just the rough modification (4 chosen systems run in parellels, other systems were executed one by one as before.) can increase my program's performance from 40->50 fps.   Step 2   When I found a bottleneck in a certain system, I divided all components of a certain type into many groups (about 4), then process each group as a thread. If it has to access some share data, which is not so often, I used std::mutex. Again, after modification in the single most CPU-intensive function, I gained overall performance from 50->65 fps.   These two experiments created feeling that it is free for me.   It is so easy ... that looks like a trap. The reason might be that I had tried to optimize my program by using Pooling for a few weeks, performance increase only 5%, while this multi-core takes only 1 day to learn & code.   Edit2: Yay, thank everyone for great knowledge!, I should post this sooner.  spamming +1
  12. JoeJ, great link (I am printing your code.)  I agree that my approach (OP) is sub-optimal, it is only a prototype to taste the multicore power.   :D Edit: I took a look at JoeJ's topic http://www.gamedev.net/topic/679252-multithreading-c11-vs-openmp/ Does it mean std::async?  
  13. :)  Thank!     I have edited OP to provide more detail.
  14. Is there any link to for Component based architecture in some complex case / real case  that objects has a lot of relation to each other?   I have faced some difficulty when tried create some relation Ex. Bullet-Component rotating around Rocket-Component.   It is hard to find good links, here is what I have :- a lot of text, link to many others place ....          http://gbgames.com/blog/2010/10/state-of-the-art-game-objects/  textbook-like, gang of four ...........        http://gameprogrammingpatterns.com/component.html religious-like description .........             http://t-machine.org/index.php/2007/12/22/entity-systems-are-the-future-of-mmog-development-part-3/    great tutorial but only basic ........  http://www.raywenderlich.com/24878/introduction-to-component-based-architecture-in-games apply with Pooling .........   http://bitsquid.blogspot.se/2014/08/building-data-oriented-entity-system.html None of these links show how to manage relation.   The order of execution of system (that manage each type of Component) seems to important too (Ex. Physic must before Graphics), but none of these links describe it.   I am noob, help!   Edit The problem is mainly "Where should I store the relation?   Bullet or Rocket?  Something above them?"     If I create some component/system that depends on two (e.g. BulletRocketSystem) , I will have to aware the order of execution. BulletRocketSystem should execute after Bullet and Rocket's system.   If Bullet will be deleted by Bullet_System's command, the BulletRocketSystem must be notified and remove reference of it.   This promotes couple between System, which is bad. Moreover, there have to be a headquarter to enforce the order, I don't know if there is non-ugly way to do it.   ---   Thank for a lot of responses, I have learned a lot. +1 all   @Alberth:  Thank!   I forgot to think about it carefully.   I should not force myself to use entity system to solve everything.   @Norman Barrows:  You are right.  Unity does it, so I followed it.   I do it for business (hopefully).   @phil_t:  I have edited OP.  XD   @Tangletail:   You caught me.  Rocket should = Shootable + HP + Physics + Graphics + ....   I hope this is what you mean.
  15. I have a data structure : pool of values.   (not pool of pointers) When I called create(), it will return Handle.     Here is a draft.  Everything is good so far.      template<class T> class Pool{         std::vector<T> v;                   //store by value         Handle<T> create(){  .... }     }     template<class T> class Handle{         Pool<T>* pool_;         int pool_index_;         T* operator->() {             return pool_->v.at(pool_index_);         }         void destroy(){             pool_-> ... destroy() .... mark "pool_index_" as unused, etc ....         }     } Now I want Handle<> to support polymorphism.  Many experts have kindly advised me to use weak_ptr, but I am left in blank, don't know how to do it. The major part that I am stuck is :- - Should create() return weak_ptr, not Handle?        .... or should Handle encapsulate weak_ptr?   - If it return weak_ptr for user's program, ...         how weak_ptr would know pool_index_?  It doesn't have such field.   - If the user cast weak_ptr/Handle to a parent class pointer as this example, there are many issues as followed.    class B{} class C : public B { } .... {      Pool<C> cs;      Handle<C> cPtr=cs.create();      Handle<A> aPtr=cPtr; // casting // expected to be valid, but don't know ... how?      aPtr->destroy()   ;                   // aPtr will invoke Pool<A>::destroy  which is wrong!                                            //  Pool<C> is the correct one, not Pool<A>      aPtr.operator->() ;                   // face the same problem } I know, I am noob, yeah.   Edit: I found a solution, so I think I should share here.   The solution (suggested by 1litre ) is to let every Pool<T> derived from Pool_interface.   Pool_interface have get/set, everything manipulate in term of void*   Instead of caching  Pool<T>* pool_; I must caching :-  Pool_interface* pool_; The get/set have to be encapsult again, e.g. return static_cast<T*>(pool_.get(index));
  16. @Alberth ;  No, I don't want to store Derived in std::vector<T>.  I know it is impossible.   I just want the handle to be safely cast-able, i.e. bad thing not happen after casting when operator->()  or destroy().  XD   Edit: An expert tell me a solution, I have edited to show it in OP.
  17.   :( , that is what I am doing, but thank Alberth.   I just hope that there is a way to cast Handle<Derive> to Handle<Base> while the destroy() is still valid.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!