I'm building a small game with SDL. I've a class GameObject which is the main class for representing objects in my game. The different behaviors are solved my components you can inject from the outside:
#include "Input.h"
class GameObject
{
public:
void setInput(Input* input)
{
input->setGameObject(this);
this->input = input;
}
}
class GameObject; // cannot #include "GameObject.h"
class Input
{
private:
GameObject* object;
public:
void update(float elapsedTime)
{
// do fancy stuff on the GameObject object
}
void setGameObject(GameObject* object)
{
this->object = object;
}
}
The Input class has to work on the GameObject instance. I have a cyclic reference now which is not a good idea I guess?
Edit: I adjusted my example to make it clearer. I have some of these components like the Input class and I've to use this class GameObject; statement since I cannot include the header file.
So if I understood it correctly I've a cyclic reference!? To solve that I would have to use an interface and add this to setGameObject(InputInterface* object). But I cannot predict what functions/member are needed for access of the GameObject because there are different components used (e.g. PlayerInput, DemoInput, AiInput, ...).
It seems you're using raw pointers (personally I think this is a bad idea), so I see no problem in having this cyclic reference, just remember to check for null.
If you were using smarter pointer types, in this case you would use a strong reference in one direction (the one that "contains" the other) and a weak reference in the other (the one that only needs a way to communicate).
For example, your game object probably owns the input mechanism; but the input mechanism just needs a way to communicate the input to the game object.
std::weak_ptr is used to break circular references of std::shared_ptr.
See: http://en.cppreference.com/w/cpp/memory/weak_ptr
Also, check if your input really needs a hold on the whole game object, or just some object that has certain interface. In that case, event mechanisms or the delegate pattern could help you remove some hard dependencies.
Cyclic references or two-sided reactivity is not uncommon.
For example, say we have a client/server relationship. Based on changes on the client or the server for, say, a webapp, the server can decide to update the client, or the client can forward an activity or action that the user has taken that requires a client's response. Either way, both might have a reference to the same data or to each other, which requires "references..." or do they? Sometimes, it can be more helpful to decouple the references from the interface to modify the data pointed to by the references.
The general response for this, much like web communications, is asynchronous I/O or message passing, and this is not an unusual pattern in even a game--often times, single-player games can make use of the message-passing model (think SimCity's GlassBox simulation with "agents" or MMORPGs with actual networking messages/packets).
If you're concerned about "coupling," perhaps you should consider various async techniques to prevent classes from having built-in callbacks to other modules that require their definitions; callbacks/reactor functions are a very common occurrence--Boost.Signals2 has a nice example of how this might be used, as well as std::async, I believe. Another option is to simply abstract everything with message passing, much like peer-to-peer networking, and encapsulate each module of your engine with message-passing/receiving modules. This would also make diagnostics easier to implement, provided an external module could "peek" at the metadata of messages.
Related
I sometimes come across, mostly when working with old code, the situation that one class acts as a mere forwarding of the calls to another class. Imagine there is a old controller which controls somethings however some of those can be dedicated to a new class. Now, the old controller will call the new class interface.
Ex.
class Controller {
public:
void addObject(const std::string & id,
const Object * obj) {
m_Wrk.addObject(id, obj);
}
private:
Worker m_Wrk;
};
class Worker {
public:
void addObject(const std::string & id,
const Object * obj) {
//do actual adding
}
};
Now, when thinking about testing the software, the interfaces might need to be tested in both classes, and it is harder in the controller as it does not mostly as it is necessary to check worker changes on controller tests.
Is this usage particularly bad or is it okay to use this kind of design in an already existing code as explained above.
Thanks
It's hard to answer whether this code is good or bad - it depends on circumstances. The code in question (except for the fact that m_Wrk field should be a pointer) is a PImpl pattern, which is a kind of a bridge pattern. This pattern is used to split the abstraction and implementation so that they can change independently.
For example, if you write a C++ library and you'd like to provide a stable ABI which does not change if there're no changes in public interface, you could put the Controller interface in header, together with forward-declaration of Worker class, and put both interface and implementation of Worker in .cpp file. When Worker changes, the Controller ABI remains the same. If the implementation details were placed directly in Controller class, the ABI might change.
Also, such pattern (Bridge in general) allows you to use different implementations of the abstraction given, so, it's possible to separate inheritance in terms of interface extension and inheritance in terms of Liskov substitution.
Also, if the Controller implements the same interface as Worker, in future it can implement some additional behavior, like in the proxy pattern.
If one of these situations takes place in your project (or may take place in future), it's probably a good code. If no, it's just an unnecessary complication.
(Refer Update #1 for a concise version of the question.)
We have an (abstract) class named Games that has subclasses, say BasketBall and Hockey (and probably many more to come later).
Another class GameSchedule, must contain a collection GamesCollection of various Games objects. The issue is that we would, at times, like to iterate only through the BasketBall objects of GamesCollection and call functions that are specific to it (and not mentioned in the Games class).
That is, GameSchedule deals with a number of objects that broadly belong to Games class, in the sense that they do have common functions that are being accessed; at the same time, there is more granularity at which they are to be handled.
We would like to come up with a design that avoids unsafe downcasting, and is extensible in the sense that creating many subclasses under Games or any of its existing subclasses must not necessitate the addition of too much code to handle this requirement.
Examples:
A clumsy solution that I came up with, that doesn't do any downcasting at all, is to have dummy functions in the Game class for every subclass specific function that has to be called from GameSchedule. These dummy functions will have an overriding implementation in the appropriate subclasses which actually require its implementation.
We could explicitly maintain different containers for various subclasses of Games instead of a single container. But this would require a lot of extra code in GameSchedule, when the number of subclasses grow. Especially if we need to iterate through all the Games objects.
Is there a neat way of doing this?
Note: the code is written in C++
Update# 1: I realized that the question can be put in a much simpler way. Is it possible to have a container class for any object belonging to a hierarchy of classes? Moreover, this container class must have the ability to pick elements belonging to (or derive from) a particular class from the hierarchy and return an appropriate list.
In the context of the above problem, the container class must have functions like GetCricketGames, GetTestCricketGames, GetBaseballGame etc.,
This is exactly one of the problems that The "Tell, Don't Ask" principle was created for.
You're describing an object that holds onto references to other objects, and wants to ask them what type of object they are before telling them what they need to do. From the article linked above:
The problem is that, as the caller, you should not be making decisions based on the state of the called object that result in you then changing the state of the object. The logic you are implementing is probably the called object’s responsibility, not yours. For you to make decisions outside the object violates its encapsulation.
If you break the rules of encapsulation, you not only introduce the runtime risks incurred by rampant downcasts, but also make your system significantly less maintainable by making it easier for components to become tightly coupled.
Now that that's out there, let's look at how the "Tell, Don't Ask" could be applied to your design problem.
Let's go through your stated constraints (in no particular order):
GameSchedule needs to iterate over all games, performing general operations
GameSchedule needs to iterate over a subset of all games (e.g., Basketball), to perform type-specific operations
No downcasts
Must easily accommodate new Game subclasses
The first step to following the "Tell, Don't Ask" principle is identifying the actions that will take place in the system. This lets us take a step back and evaluate what the system should be doing, without getting bogged down into the details of how it should be doing it.
You made the following comment in #MarkB's answer:
If there's a TestCricket class inheriting from Cricket, and it has many specific attributes concerning the timings of the various innings of the match, and we would like to initialize the values of all TestCricket objects' timing attributes to some preset value, I need a loop that picks all TestCricket objects and calls some function like setInningTimings(int inning_index, Time_Object t)
In this case, the action is: "Initialize the inning timings of all TestCricket games to a preset value."
This is problematic, because the code that wants to perform this initialization is unable to differentiate between TestCricket games, and other games (e.g., Basketball). But maybe it doesn't need to...
Most games have some element of time: Basketball games have time-limited periods, while Baseball games have (basically) innings with basically unlimited time. Each type of game could have its own completely unique configuration. This is not something we want to offload onto a single class.
Instead of asking each game what type of Game it is, and then telling it how to initialize, consider how things would work if the GameSchedule simply told each Game object to initialize. This delegates the responsibility of the initialization to the subclass of Game - the class with literally the most knowledge of what type of game it is.
This can feel really weird at first, because the GameSchedule object is relinquishing control to another object. This is an example of the Hollywood Principle. It's a completely different way of solving problems than the approach most developers initially learn.
This approach deals with the constraints in the following ways:
GameSchedule can iterate over a list of Games without any problem
GameSchedule no longer needs to know the subtypes of its Games
No downcasting is necessary, because the subclasses themselves are handling the subclass-specific logic
When a new subclass is added, no logic needs to be changed anywhere - the subclass itself implements the necessary details (e.g., an InitializeTiming() method).
Edit: Here's an example, as a proof-of-concept.
struct Game
{
std::string m_name;
Game(std::string name)
: m_name(name)
{
}
virtual void Start() = 0;
virtual void InitializeTiming() = 0;
};
// A class to demonstrate a collaborating object
struct PeriodLengthProvider
{
int GetPeriodLength();
}
struct Basketball : Game
{
int m_period_length;
PeriodLengthProvider* m_period_length_provider;
Basketball(PeriodLengthProvider* period_length_provider)
: Game("Basketball")
, m_period_length_provider(period_length_provider)
{
}
void Start() override;
void InitializeTiming() override
{
m_period_length = m_time_provider->GetPeriodLength();
}
};
struct Baseball : Game
{
int m_number_of_innings;
Baseball() : Game("Baseball") { }
void Start() override;
void InitializeTiming() override
{
m_number_of_innings = 9;
}
}
struct GameSchedule
{
std::vector<Game*> m_games;
GameSchedule(std::vector<Game*> games)
: m_games(games)
{
}
void StartGames()
{
for(auto& game : m_games)
{
game->InitializeTiming();
game->Start();
}
}
};
You've already identified the first two options that came to my mind: Make the base class have the methods in question, or maintain separate containers for each game type.
The fact that you don't feel these are appropriate leads me to believe that the "abstract" interface you provide in the Game base class may be far too concrete. I suspect that what you need to do is step back and look at the base interface.
You haven't given any concrete example to help, so I'm going to make one up. Let's say your basketball class has a NextQuarter method and hockey has NextPeriod. Instead, add to the base class a NextGameSegment method, or something that abstracts away the game-specific details. All the game-specific implementation details should be hidden in the child class with only a game-general interface needed by the schedule class.
C# supports reflections and by using the "is" keyword or GetType() member function you could do these easily. If you are writing your code in unmanaged C++, I think the best way to do this is add a GetType() method in your base class (Games?). Which in its turn would return an enum, containing all the classes that derive from it (so you would have to create an enum too) for that. That way you can safely determine the type you are dealing with only through the base type. Below is an example:
enum class GameTypes { Game, Basketball, Football, Hockey };
class Game
{
public:
virtual GameTypes GetType() { return GameTypes::Game; }
}
class BasketBall : public Game
{
public:
GameTypes GetType() { return GameTypes::Basketball; }
}
and you do this for the remaining games (e.g. Football, Hockey). Then you keep a container of Game objects only. As you get the Game object, you call its GetType() method and effectively determine its type.
You're trying to have it all, and you can't do that. :) Either you need to do a downcast, or you'll need to utilize something like the visitor pattern that would then require you to do work every time you create a new implementation of Game. Or you can fundamentally redesign things to eliminate the need to pick the individual Basketballs out of a collection of Games.
And FWIW: downcasting may be ugly, but it's not unsafe as long as you use pointers and check for null:
for(Game* game : allGames)
{
Basketball* bball = dynamic_cast<Basketball*>(game);
if(bball != nullptr)
bball->SetupCourt();
}
I'd use the strategy pattern here.
Each game type has its own scheduling strategy which derives from the common strategy used by your game schedule class and decouples the dependency between the specific game and game schedule.
I would like to know if it's bad practice to have a static container in a class to store all the pointers to the class' objects so they can all be easily accessed by the base classes of the program. This is for a game and I saw it on sdltutorials dot com, and I find it very useful. It would allow me to have a very neat structure for my game and I don't really see a downside doing this, but I know I have to be careful with "global" access and maybe there's a negative effect I'm not seeing right now.
Here is the context/example. The game has a base class with basic methods such as Loop(), Render(), PlayAudio(), CleanMemory(). The idea is to have individual objects to have the same methods being executed inside the base method. Example in pseudocode:
Game::Render() {
for (iterate all enemies in static container) {
current_enemy::Render();
}
}
To be sure, the static member inside the class would look like this:
static std::vector<Enemy*> EnemyList;
So this way, when your game is executing the base Render() method, for example, you can iterate all the enemies in the enemies' class static container and execute all their individual Render() methods, then do the same for environment objects, then for the player, etc.
I would just like to make sure I'm aware of any downside/complication/limitation I might encounter if I choose this method to build my game, because I don't see any right now but I know a have to be careful with static and global stuff.
Thanks very much for your time.
It is certainly convenient, however a static variable or a Singleton are nothing more than global variables; and having global variables comes with drawbacks:
the dependencies of a function become unclear: which global does it rely upon ?
the re-entrancy of a function is compromised: what if current_enemy.render() accidentally calls Game::Render() ? it's an infinite recursion!
the thread-safety of a function is compromised, unless proper synchronization takes place, in which case the serialized access to the global variable bog down the performance of your concurrent code (because of Amdahl's Law)
It might seem painful and pointless to explicitly pass a reference to an instance of Game wherever you need to, however it leaves a clear path of dependencies that can be followed and as the software grows you will appreciate explicitness.
And there is, of course, much to be said about transforming the program to have two instances of Game. While it might seem incongruous in this precise situation, in general it is wise not to assume that it will never be necessary in the future, for we are no oracles.
Different people may have different opinions about this. I can give you some advice on how to store your static objects in a better way.
Use the singleton pattern for a class which stores your objects:
class ObjectManager
{
private:
std::vector<Enemy*> enemies_;
std::vector<Friend*> friends_;
...
public:
void add(Enemy* e) { enemies_.push_back(e); }
...
const std::vector<Enemy*> enemies() const { return enmies_; }
...
private:
static ObjectManager* instance_;
public:
static ObjectManager* Get() { return instance_; }
static void Initialize() { instance_ = new ObjectManager(); }
}
You can access it like that (example with C++11 ranged-based for):
void Game::Render() {
for(auto e : ObjectManager::Get()->enemies()) {
e->Render();
}
}
This is especially convenient for subclasses which want to access information about the world. Normally you would have to give a pointer to ObjectManager to everyone. But if you have only one ObjectManager anyway the singleton pattern may remove clutter from your code.
Don't forget to create the singleton at the beginning of your program by calling ObjectManager::Initialize();.
I would not suggest doing this the way you are. At this point you may as well have a bare global variable in a namespace, it is the same thing you are doing right now.
I also do not suggest using singletons.
When should the Singleton pattern NOT be used? (Besides the obvious)
The best way to approach things is to do good old parameter passing (dependency injection) wherever possible. With careful design this is feasible system wide, and it avoids all the problems you have with globally accessible resources.
When you don't have the luxury of designing your system in such a way, and you are working within existing code that already has quite a bit of trouble with singleton dependence, or loss of locality between resources several levels removed from where they are needed (and you cannot afford to modify the interfaces to cascade dependencies downward) this may not be useful advice.
A middle-ground between bare global and singleton is the service-locator. Many people still consider service-locator an anti-pattern, but most people also agree that it is less bad than the singleton since it offers a certain level of abstraction and decouples creation from supplying the object which means you can offer up a derived class easily if your design or environment changes.
Here is a description of the pattern:
http://gameprogrammingpatterns.com/service-locator.html
And here is a discussion about the singleton vs service-locator.
If Singletons are bad then why is a Service Container good?.
I like the highest voted (but not accepted) answer best.
When I was younger, I used a tool called Game Maker a lot. I started to learn to program from it. I'm far beyond that now, but looking back on it, some of it's features and designs are quite interesting. I'm wondering- How would I implement functionality similar to this tool using C++?
I'm wondering about:
Objects/classes
Game Maker had a list of 'Objects' that you would create which were essentially just different classes all derived from the same base class (I'll call it GameObject for now) amd a system function called 'instance_create' that would take an object type as a paramater.
In c++ this would look something like this (Though syntatically very incorrect):
class MyGameObject : GameObject
{
//...
}
GameObject instance_create(class objecttype)
{
objecttype newinstance = new objecttype();
return newinstance
}
GameObject* gameobjectinstance = instance_create(MyGameObject);
How would I go about implementing that?
system variables/functions
Game Maker had system variables and functions that could be accessed from anywhere. Period. Anywhere. I'm thinking globals, but I know that's bad design. I'm thinking Having a global class, and have the variables/functions as static, but then they cannot be altered. How would I do that?
var
Game Maker had only one data type- a var. It could be a string, an integer, a decimal, anything. And there were system functions for conversion between those.
Lastly, how could I define the object types in some kind of script? Like, if I want to add a new type of object, create a new script? I don't think C++ can create object types at runtime, so how would I do this?
Using a template.
template<typename T> GameObject* instance_create()
{
return new T;
}
GameObject* gameobjectinstance = instance_create<MyGameObject>();
However, the design you have specified is highly questionable (at best) and definitely not suited to C++. You should strive to implement a well-designed system, and one appropriate to the language, not re-create a system from the past.
I especially think that since you mention run-time interpretation of scripts, that in fact the GameMaker classes and C++ classes have nothing to do with each other. And you definitely cannot create C++ classes at run-time, nor can you pass types around at run-time, nor can you instantiate templates at run-time.
You would be best suited simply whipping out a scripting language, such as Lua, and writing only the necessary high-performance components in C++.
Game Maker enables us to control game functionality through "objects", each composed out of "events", which are triggered at certain times during a game. Within events are "actions". Firstly, it's worth noting that comparing Game Maker development with C++ is like comparing chalk and cheese. However, theoretically speaking, I'd imagine you could mirror GM functionality (albeit very inefficiently) in C++ as follows:
The base object class could look something like this:
class CObjectBase
{
public:
CGameSprite* sprite;
int x, y;
...
virtual void onEventCreate( void ) {};
virtual void onEventDestroy( void ) {};
...
virtual void onEventKeyPressedUp( void ) {};
virtual void onEventKeyPressed...
...
... (there are lots of these)
// The draw event in GM (from memory) had in-built functionality:
virtual void onEventDraw( void )
{
CGameEngine::getSingleton()->DrawSpriteAtLocation( sprite, x, y );
}
};
You'd derive from this class and override the functions ("events") that are relevant to your object (the statements that compose these functions are your "actions"). Then there would be some sort of object instance manager singleton class which holds a list of all object instances in the current "room" and loops through each every frame (and handles instancing), triggering relevant events by calling their respective functions.
Interestingly, this actually roughly demonstrates why a system like Game Maker lacks a degree of efficiency. There is additional, unnecessary overhead that exists in order to keep options open for the developer. The bloated base object that all objects derive from is often overkill for specific situations. For example, imagine an object with just two events used out of 50 - the object manager still blindly checks for all these other events even if they aren't utilised. Obviously optimisations can be made, but overall, the breadth of the engine ultimately results in reduced performance.
As for your query relating to a single 'var' type, as has been stated already, this is more a characteristic of scripting, not C++. This proves that Game Maker cannot simply be modeled by C++ alone.
I've got a game engine where I'm splitting off the physics simulation from the game object functionality. So I've got a pure virtual class for a physical body
class Body
from which I'll be deriving various implementations of a physics simulation. My game object class then looks like
class GameObject {
public:
// ...
private:
Body *m_pBody;
};
and I can plug in whatever implementation I need for that particular game. But I may need access to all of the Body functions when I've only got a GameObject. So I've found myself writing tons of things like
Vector GameObject::GetPosition() const { return m_pBody->GetPosition(); }
I'm tempted to scratch all of them and just do stuff like
pObject->GetBody()->GetPosition();
but this seems wrong (i.e. violates the Law of Demeter). Plus, it simply pushes the verbosity from the implementation to the usage. So I'm looking for a different way of doing this.
The idea of the law of Demeter is that your GameObject isn't supposed to have functions like GetPosition(). Instead it's supposed to have MoveForward(int) or TurnLeft() functions that may call GetPosition() (along with other functions) internally. Essentially they translate one interface into another.
If your logic requires a GetPosition() function, then it makes sense turn that into an interface a la Ates Goral. Otherwise you'll need to rethink why you're grabbing so deeply into an object to call methods on its subobjects.
One approach you could take is to split the Body interface into multiple interfaces, each with a different purpose and give GameObject ownership of only the interfaces that it would have to expose.
class Positionable;
class Movable;
class Collidable;
//etc.
The concrete Body implementations would probably implement all interfaces but a GameObject that only needs to expose its position would only reference (through dependency injection) a Positionable interface:
class BodyA : public Positionable, Movable, Collidable {
// ...
};
class GameObjectA {
private:
Positionable *m_p;
public:
GameObjectA(Positionable *p) { m_p = p; }
Positionable *getPosition() { return m_p; }
};
BodyA bodyA;
GameObjectA objA(&bodyA);
objA->getPosition()->getX();
Game hierarchies should not involve a lot of inheritance. I can't point you to any web pages, but that is the feeling I've gather from the several sources, most notably the game gem series.
You can have hierarchies like ship->tie_fighter, ship->x_wing. But not PlaysSound->tie_fighter. Your tie_fighter class should be composed of the objects it needs to represent itself. A physics part, a graphics part, etc. You should provide a minimal interface for interacting with your game objects. Implement as much physics logic in the engine or in the physic piece.
With this approach your game objects become collections of more basic game components.
All that said, you will want to be able to set a game objects physical state during game events. So you'll end up with problem you described for setting the various pieces of state. It's just icky but that is best solution I've found so far.
I've recently tried to make higher level state functions, using ideas from Box2D. Have a function SetXForm for setting positions etc. Another for SetDXForm for velocities and angular velocity. These functions take proxy objects as parameters that represent the various parts of the physical state. Using methods like these you could reduce the number of methods you'd need to set state but in the end you'd probably still end up implementing the finer grained ones, and the proxy objects would be more work than you would save by skipping out on a few methods.
So, I didn't help that much. This was more a rebuttal of the previous answer.
In summary, I would recommend you stick with the many method approach. There may not always be a simple one to 1 relationship between game objects and physic objects. We ran into that where it was much simpler to have one game object represent all of the particles from an explosion. If we had given in and just exposed a body pointer, we would not have been able to simplify the problem.
Do I understand correctly that you're separating the physics of something from it's game representation?
i.e, would you see something like this:
class CompanionCube
{
private:
Body* m_pPhysicsBody;
};
?
If so, that smells wrong to me. Technically your 'GameObject' is a physics object, so it should derive from Body.
It sounds like you're planning on swapping physics models around and that's why you're attempting to do it via aggregation, and if that's the case, I'd ask: "Do you plan on swapping physics types at runtime, or compile time?".
If compile time is your answer, I'd derive your game objects from Body, and make Body a typedef to whichever physics body you want to have be the default.
If it's runtime, you'd have to write a 'Body' class that does that switching internally, which might not be a bad idea if your goal is to play around with different physics.
Alternatively, you'll probably find you'll have different 'parent' classes for Body depending on the type of game object (water, rigid body, etc), so you could just make that explicit in your derivation.
Anyhow, I'll stop rambling since this answer is based on a lot of guesswork. ;) Let me know if I'm off base, and I'll delete my answer.