c++ inhertiance

Started by
5 comments, last by BitMaster 9 years, 6 months ago

I'm working on a basic game and trying to do steering algorithms and my problem I believe is routed in inheritance of classes.

So basically I have a class called GameplayObjects which have some variables like speed, velocity, etc... I'm now trying to create a class called Steering which is derived from GameplayObjects so I have access to the objects speed and stuff. Now my problem comes in when trying to write the member functions of steering because in order to calculate the needed vectors for the steering I'm using two different GameplayObjects.

So for instance for a seek function I need to subtract the target and source positions but can't get it to work, I've tried everything I can think of like making Getfunctions inside of GameplayObjects to return position but still got errors.

so basically here's what I've tried with no luck....

void Steering::seek (GameplayObjects source, GameplayObjects target)

{

SteeringVector = target.position - source.position;

SteeringVector = *target->Getposition - *source->Getposition; //and yes I changed the declaration of the function so that source and target are pointers

}

So I guess the question is how do I pass in to GameplayObjects and access their respective attributes like speed, position, rotation, velocity, etc.. Its been a while since I've done coding I know this has to be a simple solution but I just cant think of it....

Advertisement

Usually prefer composition over inheritance.

Inheritance means: "This thing is exactly replaceable with this other thing."

"Steering" is not a "game object". It doesn't make much sense to have a query "Please list all the game objects" and get a result "Here is some steering!" They are not normally things that get swapped around.

What you're looking for is composition: "This thing has some specific detail."

Very often you will have a system where everything relies on components. Components use inheritance. There is often a base Component class that is abstract, and a bunch of concrete components, like "SteeringComponent" in your case, or "PhysicsComponent" or "GraphicsModel" or "PointLight" or "Camera" or whatever that derive from Component. Those components themselves will usually have compositions of other parts.

Game objects will then likely have an interface to add components, remove components, list components, etc. that allow scripts and other processing to be run.

Although i do not disagree with what frob said... here's my answer to your question:

If you want this to work:


SteeringVector = target.position  - source.position;

the "position" needs to be a "protected" attribute, not a private one. A class that inherits from another class can't access their private values.

If you want this to work:


SteeringVector = *target->Getposition  - *source->Getposition

you should write target->GetPosition()... that is why "->" is there, to simplify the (*target). nomenclature.

If problems persist, post the errors.

a) The name GameplayObjects denotes a multiple of game objects (i.e. a collection), and hence should better be GameplayObject in the case you mean just one. When choosing a class name, remember the phrase "an instance of this class is-a ...".

b) The parameters of Steering::seek(GameplayObjects source, GameplayObjects target) are passed in as copies (as long as GameplayObjects is not a typedef). It is better to pass them by references, where suitable also by const references: Steering::seek(const GameplayObject & source, GameplayObject & target)

c) Steering is a kind of behavior (notice that the term is a verb), opposed to GameplayObject what denotes a, well, object. This gives a hint that deriving Steering from GameplayObject may not be correct. The fact that Steering meaninglessly inherits position and velocity hints at the same. So Steering seems better to be an own base class of Fleeing, Wandering, Evading, and so on. This allows that the current behavior can be selected and plugged into the GameplayObject of interest (composition over inheritance).

d) With the same fundamental idea as in c) it is debatable whether physical attributes like velocity and (in a less manner also) position should actually be part of GameplayObject. Thinking of composition, a PhysicsBody may store velocity and (to get rid of sudden changes in movement) mass. A Placement may be used to store current position and orientation.

A concept like the above is what frob mentioned already. If a Steering component is plugged into a generic GameplayObject object, it uses the also plugged in PhysicsBody to compute the next Placement of the GameplayObject. It does so by considering the Placement of one or more specific other GameplayObject objects in vicinity. Of course, such a Steering behavior requires a PhysicsBody to be available on the own steered GameplayObject. On the other hand, the concept allows to, for example, flee from a GameplayObject that itself has no PhysicsBody because it is stationary (it still need to present an own Placement, of course).

The class' situation can now be described as: GameplayObject has or has not a PhysicsBody; it has or has not a (concrete) Steering.

I know it's not trendy these days, but in the old days we might have decomposed the objects into smaller objects and inherited from them.

For example, you might have a Targetable object.


class Targetable
{
public:
    Position get_target_position() const
    { return target_position_; }
 
private:
    Position target_position_;
};

You also might have a Steerable object.


class Steerable
{
public:
    void target(Targetable const& target)
    { target_position_ = target.get_target_position(); }

    void update_position(Tick const& tick)
    { current_position_ += (tick - starting_tick_) * (target_position_ - current_position_); }
 
private:
    Position target_position_;
    Position current_position_;
    Tick     starting_tick_
};

Then, you can classify various objects accordingly.


class GameObject
: public Targetable, public Steerable
{
public:
    void update(Tick const& tick)
    {
        update_position(tick);
        increment_sprite();
    }
};

Stephen M. Webb
Professional Free Software Developer

Ok so I tried like every possible combination and I guess maybe my problem the whole time was that I can't just subtract two d3dxvector3's I needed to use D3DXVec3Subtract

This doesn't work:


SteeringVector = &target.GetPosition() - &source.GetPosition();

But this does:


D3DXVec3Subtract(&SteeringVector, &target.GetPosition(), &source.GetPosition());

without inheriting from GameplayObject

On a side note though with inheritiance it would not let me access the protected data of the base class I kept getting "Error 1 error C2248: 'GameplayObject::position' : cannot access protected member declared in class 'GameplayObject' " which I thought the whole point of putting it under protected instead of private was so subclasses would have access directly to the data...

Thank you everyone for your help and advice...

This doesn't work:



SteeringVector = &target.GetPosition() - &source.GetPosition();


I wouldn't expect it to. You cannot just subtract pointers like that. Have you tried
target.GetPosition() - source.GetPosition();
instead.

This topic is closed to new replies.

Advertisement