Jump to content
  • Advertisement
Sign in to follow this  
hyyou

shorten calling-signature other game systems "s<S_Projectile>()->"

This topic is 511 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.)

Edited by hyyou

Share this post


Link to post
Share on other sites
Advertisement

I would advise you to scrap your singleton idea. It's going to hide dependencies and lead to hard-to-maintain code.

 

Access your instance of that system directly by passing a reference to the code that needs it. For example, if your System_AI needs access to the System_Projectile system, just have System_Projectile& as a parameter to System_AI's constructor and store it as a member variable. Then the dependency is clear (and you can make your member variable as terse as you want to - because for some reason (?) this is a goal for you, despite modern IDE features like intellisense).

Edited by phil_t

Share this post


Link to post
Share on other sites

@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

Edited by hyyou

Share this post


Link to post
Share on other sites

You've got quite a few anti-patterns in there, singletons, shared state, hidden dependencies, functional decomposition, and more.  I'm really tempted to address those in the post, but I will leave those and write that you're describing some major structural problems in the code. Based on your descriptions and short code snippets there are likely far better ways to accomplish those goals.

 

 

 

For the specific question, try to choose better names.  

 

Better doesn't mean shorter, but for autocomplete systems usually it means getting rid of prefixes.  When you have something named "System_xxx" you have just required 8 keystrokes for no good reason.  Instead of System_AI, System_Physics, System_Projectile, you could use AI, Physics, or Projectile directly.  Then the word "Projectile" is 10 letters, do you have any shorter words than that?

 

Function names like you've got, "changeTargetToPlayer" are also too long.  The "ToPlayer" part is unneeded, the name can be picked up by parameter type. If you pass in a player type then you know they are targeting a player. If they pass in some other object type you know they are targeting that type instead.  The "change" is unneeded because these types of functions are either mutators (use to change or set or apply or write ) or accessors (read, access, query).  The other type of function is a command, but that doesn't apply in your example.  ->changeTargetToPlayer()  becomes ->target(...);

 

Combine them, and generally the code looks like "noun->verb()"  or "noun->verb(noun)".  Maybe: actor->target(opponent).  Or turret->target(activeEnemy). Accessors are similar, evaluating attributes with turret->range(), or maybe actor->target().  Since I mentioned commands I should give an example, you may have actor->runTo(destination) or turret->reset().  

 

 

I'm not entirely sure what you mean when you write "I can't call a system by the class name anymore". It suggests that you are confusing functionality with instances. Better naming can help with that, too. Think about if you've got a noun, a verb, or a modifyer. Do you have a projectilePool, or a projectileCollection, or a room that contains projectiles, or weapon that fires projectiles? A projectile factory or projectile generator

 

 

 

Naming things is a hard task in programming. When you discover a name can be improved, take action and rename it using automated tools.

Share this post


Link to post
Share on other sites

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.

Edited by hyyou

Share this post


Link to post
Share on other sites

What do you think about Unity's approach?. It has some static methods to access its subsystems. eg.

Input.KeyPress();
Physics.RayCast();
Resources.Load();
Debug.Log();

They are global, and everyone can access them, there's no problem in that. Also, Jason Gregory on its Game Engine Architecture book suggests something similar, every major subsystem is global and has an StartUp and Shutdown method.

On the other hand I don't think "Projectile" is a major subsystem at all :)

Share this post


Link to post
Share on other sites
class SystemB{
     SystemA* systemA; 
     public: void update()
        { 
            systemA->doSomething(); 
        } 
};

 
That is the PIMPL pattern, short for "Pointer to Implementation".  An alternate version might be:
 

class Physics{
     ActualPhysics* actualPhysics; 
     public: void update()
        { 
            actualPhysics->update(); 
        } 
};

It allows for faster compilation in large systems, since the header files don't change when the implementation changes.

 

From your descriptions, using PIMPL right now is not a good fit.

 

On the other items, those are your choice. Each has been discussed by other replies, so I won't.

Share this post


Link to post
Share on other sites

i'd start by addressing the issues mentioned above.

as code becomes better organized, read-ability and write-ability tend to increase.

after that, if its still too much typing, check into macros, or write your own macro pre-processor - that's what i did.

i've been coding since 1978, both games and apps. i tend to write the code in my head first, then simply type it in. So typing is the bottleneck to code entry.  So i wrote a macro processor that minimizes keystrokes. I now do all my coding in the macro processor language, then translate it to c++.

Note that even with macros, long convoluted variable and function names will still require lots of typing, unless you expand them in the macro.

An example:

in caveman v1.0 the current player was:  caveman[current_caveman]

when i stared version 3.0, i knew i'd be typing that 10,000 times. so i changed it to:   cm[cm0].

and even that gets long after a while.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!