Page 1 of 1

Design Pattern for an NPC or PC entering a car

Posted: Tue May 15, 2012 8:01 pm
by BrightBit
Hello,

I want the player of my project to be able to enter a car next to him by pressing a certain key (e.g. 'E' for Enter). The controls for the car differ - of course - from the controls for a player on foot. So I thought using the State Pattern could separate these two behaviours. But here's my problem: Who is the context? Who is responsible for the transition of these states?

Image

You might ask yourself: What's your problem with just using some kind of context class? My project uses a game object component system, so a car is build up by several components (e.g. visual component, drivable component, etc.) and a human, too (visual component, health component, etc.). This is true for a human controlled by the player as for humans controlled by the CPU. An NPC would also have an AI Component that should be able to enter cars as well and this is the root of my problem: the AI Component keeps track of what the NPC (a human) is doing (walking or driving) so it is the Context but since the AI component has to trigger the entering of a car it is also one of its own states.

What can I do about it? Am I missing something? Is there a better way of organising a mechanism for 'enterable' cars with game object components?

Re: Design Pattern for an NPC or PC entering a car

Posted: Tue May 15, 2012 8:29 pm
by bstone
You will have to employ one more pattern: KISS. :wink:

Re: Design Pattern for an NPC or PC entering a car

Posted: Tue May 15, 2012 11:15 pm
by BrightBit
Well, sorry, this doesn't really help me. Can you please tell me which parts are unnecessary or how I can simplify my "design"?

A game object component system is used by many modern game engines or games. The state pattern is also widely used and I just don't know how to combine these two things in an elegant manner.

After even more thinking this is what I came up with:

Image

Now the AI Component is the aforementioned Context and can switch between two states (Walking and Driving). It still doesn't feel right because the Driving State of the Human AI Component has to know/implement the behaviour and phyiscs of a Car "Class".

Maybe it's really just me but I'm really not able to see a good solution here.

Re: Design Pattern for an NPC or PC entering a car

Posted: Wed May 16, 2012 5:48 am
by bstone
A game object component system is used by many modern game engines or games
.
So is that the only reason for you to use it? My advice is still to do the simplest thing that works, then improve on that if needed. If you don't really understand why you have to use all those components and how they benefit your project then you will have that and similar questions raising every few minutes.

Re: Design Pattern for an NPC or PC entering a car

Posted: Wed May 16, 2012 12:09 pm
by syedhs
Probably just study the existing design of GameObject/Components already employed in well known game engine. I think there is a term for this: controller.

Re: Design Pattern for an NPC or PC entering a car

Posted: Wed May 16, 2012 3:21 pm
by BrightBit
As John David Wheeler said: "All problems in computer science can be solved by another level of indirection [...]". I want to use the Component System because of its flexibility and because of its reduction of code redundancy. You have to get used to this kind of system but just because it's difficult to master doesn't mean that it's wrong.
My advice is still to do the simplest thing that works, then improve on that if needed.
The "simplest thing that works" is a question of defintion. What does "works" mean? I want a flexible software design that can be extended more easily than software that is programmed only for problems on close sight. Of course I can't imagine every possible problem I will encounter, so I shouldn't overdoo the whole flexible software thing but I don't think that this is the case right now.

My phrase "A game object component system is used by many modern game engines or games." wasn't meant as an argument for the component system. It was meant as an argument against your KISS principle because I don't think that modern game engines are interested in making things more complicated for nothing. But I admit it's a rather weak argument. :)

...but if the component system annoys you: How would you handle my problem with an ordinary class based concept?

@syedhs: A controller is - as far as I know - the code that decides how an entity like the player reacts to its environment on a physical basis. For example: A First Person Character controller often implements some stair stepping mechanics where it has to determine whether the geometry in front of the player is ascendable.

I already looked for solutions of existing game engines like for example the unity engine but the ones I found so far often seemed uncomplete or hacked/dirty.


Nevertheless thank you guys for at leat trying to help me. :)

Re: Design Pattern for an NPC or PC entering a car

Posted: Wed May 16, 2012 4:55 pm
by bstone
BrightBit wrote:The "simplest thing that works" is a question of defintion. What does "works" mean?
That's the right question. I assumed you wanted to develop a game, hence the advice.
BrightBit wrote:I want a flexible software design that can be extended more easily than software that is programmed only for problems on close sight. Of course I can't imagine every possible problem I will encounter, so I shouldn't overdoo the whole flexible software thing but I don't think that this is the case right now.
Now that I see what you're after I will tell you this: everybody wants that, but nobody gets it. No silver bullet here. Yes, you can have a very flexible set of abstractions that might make a specific class of problems be easier to understand, solve, and maintain. But... these are usually born after a serious number of "simple -> flexible -> simple -> flexible -> simple -> flexible..." iterations over a set of very specific problems. The funny thing is that this kind of transformation is rather hard to grasp from the final example (i.e. looking at the existing game engine components). It's something that sticks much better through experience. But even there a simple problem that doesn't map on your beautiful framework can ruin it and you will need ugly hacks to work around it.

Believe me that more often than not "simple" means more flexible and hence is your friend.
BrightBit wrote:My phrase "A game object component system is used by many modern game engines or games." wasn't meant as an argument for the component system. It was meant as an argument against your KISS principle because I don't think that modern game engines are interested in making things more complicated for nothing. But I admit it's a rather weak argument. :)
I have a simple answer to that: game engines are not games! The goal of a game engine is to suit as many potential applications as possible. Hence the bloated complexity and mix-matching incompatible things in the process. It's not their goal but their way of achieving it.
BrightBit wrote:...but if the component system annoys you: How would you handle my problem with an ordinary class based concept?
It doesn't annoy me. I just thought you were making a game and tried to take you off the unreasonably complex way of doing that. Given your initial description and the pictures you posted: you need the player to disappear then he enters a car, and appear when he exits it; the controls should switch from human to vehicle-specific and vice-versa. Here's my simple solution to that:

Code: Select all

class IControllableSubject { ... };

class Vehicle
    : public IControllableSubject
{
  ...
};

class Human
    : public IControllableSubject
{
  ...
};

class UserInputEvent { ... };

class IUserInputHandler
{
  public:
    virtual void mapUserInputTo( IControlledSubject* subject ) = 0;
};

class HumanStyleControl
    : public IUserInputHandler
{ 
  ...
};

class VehicleStyleControl
    : public IUserInputHandler
{ 
  ...
};

class Player
{
  public:
    ...

    void enterVehicle( Vehicle* target )
    {
        m_human->removeFromScene();
        m_controlledSubject = target;
        m_userInputHandler = VehicleStyleControl();
    }

    void exitVehicle()
    {
        placeHumanLeftOfTheSubject( m_controlledSubject );
        m_human->addToScene();
        m_controlledSubject = m_human;
        m_userInputHandler = HumanStyleControl();
    }

    void processUserInput( const UserInputEvent& userInput )
    {
        m_userInputHandler->mapUserInputTo( m_controlledSubject );
    }

  private:
    void placeHumanLeftToTheSubject() { ... }

    ...
};
To me it: 1) solves the task; 2) is easy to understand because it's in the problem domain as opposed to working around some abstract components; 3) is easy to extend in any direction required because the code is very simple.

decision making

Posted: Wed May 16, 2012 6:04 pm
by BrightBit
Thank you for your detailed answer. I will definitely have to think about it.
bstone wrote:It doesn't annoy me.
Sorry, maybe "annoy" isn't the right word. I'm no native speaker. I meant baffle, bother, disturb or something like that. :)

You've got some good arguments there. I want to create a game but I also want to use a component system. Maybe I should explain my decision making a bit more. I am aiming at some kind of roguelike game like nethack. The properties of the items in nethack can influence several aspects of the game, e.g. wearing a silver ring while fighting with bare hands against a vampire can kill the vampire because of the silver.
Let's take this example for my component system. I would create a SilverComponent that could be attached to any GameObject (an arbitrary item) and would therefore be able to influence aspects of the game as well by asking for "Hit" events (collisions with entities) of its GameObject and reacting to them. Another advantage in contrast to classes is the aforementioned code redundancy reduction. If you have a class that can be scripted and a class that can be animated, you'll need to inherit from both classes to create a new class that can be animated and scripted as well. The more complex your class hierarchy is, the more difficult it will get to create new classes that inherit old functionality without causing redundancy. This example might not be the best but it hopefully illustrates that it would be a lot easier to combine preexisting functionality with components.
As I said I am aware of the fact that 100% flexibility isn't possible but my vision of the game that I want to create still isn't very clear and I am hoping that a component system will help me experiment more easily (because of its flexibility).


Nevertheless I am really grateful for your critiques and comments. Kudos for you! :)

Re: decision making

Posted: Wed May 16, 2012 7:35 pm
by bstone
BrightBit wrote:Thank you for your detailed answer. I will definitely have to think about it.
You're welcome.
BrightBit wrote:I am aiming at some kind of roguelike game like nethack.
That's a serious undertaking as it is even without beating your head against the wall of components :D
BrightBit wrote:Let's take this example for my component system. I would create a SilverComponent that could be attached to any GameObject (an arbitrary item) and would therefore be able to influence aspects of the game as well by asking for "Hit" events (collisions with entities) of its GameObject and reacting to them.
What you're talking about is the double-dispatch. Hiding it behind "events" might complicate things, but the double-dispatch is a beast in itself and requires a trained hand, so that won't be easy either way.
BrightBit wrote:Another advantage in contrast to classes is the aforementioned code redundancy reduction. If you have a class that can be scripted and a class that can be animated, you'll need to inherit from both classes to create a new class that can be animated and scripted as well.
That's a common misconception that leads to clumsy and inflexible designs that are painful to both maintain and evolve. Unfortunately I see that left and right.

Use inheritance as a tool. Don't use it to reflect some properties of your domain just because they seem related. A good rule is to only use inheritance if your base class has to sent messages to derived classes. Otherwise don't use it as it introduces too much coupling into the system. Think interfaces instead. They are your best asset in building loosely coupled code around abstractions.
BrightBit wrote:The more complex your class hierarchy is, the more difficult it will get to create new classes that inherit old functionality without causing redundancy.
Not sure about redundancy but everything else is exactly what I was talking about above. Avoid complex hierarchies and use interfaces to split them into simple inheritance chains of implementations.
BrightBit wrote:This example might not be the best but it hopefully illustrates that it would be a lot easier to combine preexisting functionality with components. As I said I am aware of the fact that 100% flexibility isn't possible but my vision of the game that I want to create still isn't very clear and I am hoping that a component system will help me experiment more easily (because of its flexibility).
Well, I hope you will post about your experience in that regard when you're done with your game.
BrightBit wrote:Nevertheless I am really grateful for your critiques and comments. Kudos for you! :)
No problem. Good luck with your vampirehack! :D

Re: Design Pattern for an NPC or PC entering a car

Posted: Sat Oct 06, 2012 3:50 pm
by drwbns
Is it wise to seperate the Player class from the Character class? It seems logical for sake of switching controllers. My goal is to seperate my Player class from generic Character, Vehicle, and Controller classes. I get a little confused in deciding whether a controller should have a Controllable member or as you suggested, having the Player class contain that ( which looks better to me ). How to get the controller working without knowing which object it's controlling is the hard part. Right now, my controllers control a specific character, so I do I abstract this? Is the controller a controllableSubject also, or just the character? It seems to be the question since my controller controls a specific character. Or does the controller derive from IUserInputHandler? This seems to make a bit more sense but would leave me with the controller containing a controllableSubject instead of the Player class containing it. In bstone's example, I think Player is deriving from IUserInputHandler to be able to switch the control mapping, correct?