0

I'm having doubts on how to proceed regarding the class structure of my game/simulation framework. Please note that I am doing this mostly for my own enjoyment, I know there are lots of good solutions already out there :)

The structure of the framework has, among other things, Scenes that contain Actors. Both Scenes and Actors can behave in many different ways WRT some aspects of how stuff works internally. I have implemented such behaviours using multiple inheritance, like so:

class ActorBase : public Object { ... }; 
class Actor : virtual public ActorBase { ... };
class CollisionBehavior : virtual public ActorBase { ... }; 
class BoundingBoxCollisionBehavior : public CollisionBehavior { ... };
class MyActor : public Actor, public BoundingBoxCollisionBehavior { ... };

This way, using virtual inheritance, I can separate the implementation of what the actor is from the implementation of what the actor does (or how it does it). Both the Actor and ...Behavior classes need access to the common base class ActorBase for their implementation, but things are neatly compartmentalised and I can easily change the behaviour of an object by simply replacing the Behavior class it inherits from.

This has its limitation though: since each behaviour follows its own internal rules, and an object can inherit from a single Behavior (or else hell breaks loose because of ambiguous function calls etc), I can never have two actors with different behaviours interact with each other. Also, since I'm integrating the V8 Javascript Engine into the framework, I'd have to create wrapped child classes for each possible combination of Actor (or Scene) and their possible behaviours, and instancing these object in a mixed fashion from JS would result in a crash because, again, two object that behave differently cannot interact with each other (at least not for everything).

An alternative solution I thought would be to abandon this multiple inheritance structure in favour of something like this: each object that requires Behaviors has many arrays, one for each Behavior group (like collision behavior, movement behavior, etc), with a ...Behavior object for each possible behavior. I can give an object a default behavior and, if it's ever needed (an interaction occurs with an object with a different default behavior), I can add such behavior to one (or both) objects so that they can interact with each other - there would need to be some sort of conversion policy, but thats not an issue. This would mean having a circular reference (the object instance references the behavior instance and the behavior instance references the object it's contained in) for the behavior to be able to access the base properties it needs to do its own thing. The Behavior subclasses would also need to be friends with the Actor class, to access protected and/or private members. I'm don't really like this road that much, and I think there might be a more elegant way to solve this problem, I just haven't thought of one yet.

Thoughts? :)

Bonus Question: should I spell Behavior or BehavioUr? Not a native speaker!

EDIT: Solved the bonus question - depends or where you feel you are when on the Internet! :)

EDIT 2: Changed from Behavior to CollisionBehavior for clarity (see answer below)

7
  • 2
    Not a native speaker either, but behavior is US spelling whereas behaviour is British (or so I've been told). When in Rome, do as the Romans do :) Commented Jun 18, 2013 at 10:28
  • 1
    Actors are not behaviours (inheritance relationship) they have behaviours. I'd build up my behaviours and give them out appropriately. Commented Jun 18, 2013 at 10:30
  • 6
    "Behaviour" is the English spelling; "behavior" is the standardised misspelling used in the US. Commented Jun 18, 2013 at 10:33
  • Actors are, indeed, not behaviours. My reasoning is that, since I cannot use interfaces/protocols, this is the closest I can get. Commented Jun 18, 2013 at 10:40
  • 1
    @jrok And when on the internet, are you in London or New York. (As a general rule, international English is probably American English, if only because that is the default for a lot of spell checkers.) Commented Jun 18, 2013 at 10:41

1 Answer 1

1

I am afraid you are mixing things here. As you noted there are many different kinds of behaviors 1:

  • walking behavior
  • talking behavior
  • fighting behavior
  • ...

And of course it makes no sense to have a WalkingBehavior compare to a FightingBehavior so it makes no sense to have them share a base class either.

As such, I think that you should just use Actors and provide methods to retrieve the behaviors on those:

class Actor {
public:
    virtual WalkingBehavior const& walkingBehavior() const {
        return DefaultWalkingBehavior;
    }

    virtual FightingBehavior const& fightingBehavior() const {
        return DefaultFightingBehavior;
    }

    // ...
}; // class Actor

Where the default behavior is defined in such a way that it can interact with a more regular behavior of its class. Then, each specific interface such as FightingBehavior should provide the necessary methods to understand this behavior.

Note that this method of encoding information is extremely versatile: you can mix behaviors that are determined at compile-time and behaviors that are determined at run-time (and may evolve at run-time) without any incidence on the clients.

1 Personally I just follow my built-in browser spell-checker.

Sign up to request clarification or add additional context in comments.

3 Comments

This is indeed elegant. I'll ponder it, try to implement it and get back to you, thanks! ;)
Also, I realize I've not been clear: each behaviour "group" has its own base class from which various behaviours of that group inherit, but behaviours do not have a common base class. That was badly explained in the question. I would have a WalkingBehavior base class with many walking behaviour subclasses (up-straight, happily jumping, slouching and so on). So, following my initial implementation, an Actor subclass would have to inherit from each behavior group where needed.
Thank you, in the end I did follow your advice and went with an approach similar to what you described. It's definitely better than what I was trying to do!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.