Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Are cyclic dependencies a common thing in games dev? I ask as I keep getting into situation where I'm using and have been told more than once that they should be avoided.

I am wondering if this is just a what people say as a general rule of thumb in the software development business. and that the nature of game programming produces such dependencies.

// Foo
#include <Bar.hpp>
class Foo {
    bar& m_bar;
};

and

// Bar
class Foo;
class Bar {
    Foo* m_foo;
};

I do this alot in Ruby, but dynamic languages are more forgiving in this instance, where as static ones, not so much.

share|improve this question
    
An example, some source and/or generally more information would help us answering your question. –  Ray Dey Dec 28 '10 at 1:07
    
@Ray Dey some clarification added. –  PhilCK Dec 28 '10 at 1:25
6  
Sounds like a StackOverflow.com question. –  muntoo Dec 28 '10 at 1:35
2  
I'd agree, but the meat of the question is really in the second paragraph. I.e. "is game development special in that these sorts of dependencies happen naturally". To which of course the answer is no. –  MrCranky Dec 28 '10 at 11:06
    
@MrCranky Thank you. –  PhilCK Dec 30 '10 at 12:32

2 Answers 2

up vote 7 down vote accepted

Since you're using indirect addressing (pointers or references), and you don't need to know the contents of the other object at declaration time (only at implementation time) this will work just fine in most languages. Obviously it falls apart when you have one object containing another (because to know the size of the containing object, you have to know the full details of the contained object).

All of that is just semantics though, the fact that you can do such a thing is not a reason why you should. The problem that you'll face is that you are essentially tightly binding those two classes together. You can't have a Foo without a Bar, nor a Bar without a Foo. So you can't re-use Foo elsewhere without also dragging Bar along as well, and that may just not be appropriate. So if the only reason Foo needs to know about Bar is for one little thing, that might even be optional, that's a massive pain.

For example, if you have a character instance which knows about an navigation state structure to run its navigation logic, but in turn, the navigation state needs a back pointer to the character instance so it can get, say, its position. The navigation logic might also be applicable to vehicles, but you can't use it, because navigation is assuming that it's hooked to a character.

A much better approach to this is to understand what the back-pointers are being used for, and define an interface which can be used instead. Instead of having a Character* pointer, the navigation state has an IPositionable pointer (and Character implements IPositionable somehow). Now the navigation logic doesn't care how it is used, and can be re-used for characters, vehicles, anything. Better yet, the navigation logic could be split out into its own library / module, because it now has no awareness of anything above its own level - it's nice and self-contained.

Game development is not special in this regard. If you are producing many such tight circular dependencies like this, it is because your structures are poorly designed. This is a normal software engineering problem, and all of the same guidances apply.

share|improve this answer

Cyclic dependencies are a common design mistake in software development. Game development might be more susceptible to it, since you have a lot moving parts which have to depend on another in some way.

If you're overusing cyclic dependencies your code will turn into one tightly coupled mess.

Suppose you have Sprite class to render the player sprite on screen, a PhysicObject class for movement&collision detection, a Animator class to animate the player sprite, a PlayerControl class to apply user input to the player character.

If each class knows about the others you cannot use just a subset of these. An invisible wall might just consist of the PhysicObject. A wooden crate consist of a Sprite and a PhysicsObject and so on.

If classes have to speak to each other it is better to use an event system. Or have a parent class which encapsulates common data members. Child classes are also data members of the parent class and just manipulate the data members of the parent.

There is no single right ways to structure a game.

Another problem with cyclic dependencies is what if one of the classes is deleted? If the Foo object is deleted the Bar object has an invalid pointer and will cause an error the next time it tries to access it.

You also cannot use boosts shared pointer class if you have cyclic dependencies. Shared pointer will delete the object it points to if there are no more references to it. But if Foo points to Bar and Bar points to Foo, Foo and Bar will never be deleted and you have a memory leak.

Game entities with components:
http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

I'm reading Mike McShaffry's "Game Coding Complete" which give a quite good overview how to design and build games. It also has a bunch of code samples. Might be worth a look ;)

Regarding your code sample:
Use inclusion guards to avoid multiple includes of the same header file:

#ifndef BAR_H
#define BAR_H
class BAR {
  //class definition
};

#endif

or if you're using Visual Studio:

#pragma once
class BAR {
  //class definition
};

This will stop the compiler from complaining.

share|improve this answer
    
Thanks Stephen, the include guards where just left out for shortness sake. –  PhilCK Jan 1 '11 at 20:40
    
Ah sorry. Missing inclusion guards had me stumped for quite a while when I started the first serious c++ programming. –  Stephen Jan 1 '11 at 22:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.