In a lot of games the player can choose whether an entity will be controlled by the AI or by the player. For example in the game Little Fighter 2, the player can choose how many of a maximum of 8 characters would be AI-controlled and how many of them would be human-controlled.
I was thinking how I can achieve this in my game. Currently in my game whatever controls the characters is hardcoded into them. I even have an AIAgent abstract superclass that all AI characters derive from, and a Player class that represents the player-controlled entity.
I realized that in order to be able to choose dynamically if an entity will be controlled by the player or by the AI, I need to decouple the entity itself from "it's brain", i.e. whatever controls it.
By "the entity itself" I mean the attributes and actions of the entity: it's mass, it's image, the way it implements shooting a missile, etc. By "the brain" I mean the system that decides when, and possibly how, to act.
As I said, currently "the brain" of my entities is hardcoded in their update() function. My Player class responds to player input in it's update() method, and my AIAgent subclasses usually delegate to a StateMachine of some sort in this method.
So I was thinking: how can I decouple the entities from their "brains", in order to be able to choose dynamically whether a Monster is player or AI controlled - and without a lot of ugly code duplication.
The solution that comes to mind is creating an abstract Controller class, with subclasses that can be plugged into the entities. Then the entities simply delegate to their controllers in the 'update()` function, and the controller controls the entity through it's interface.
To demonstrate:
abstract class Entity{
// .. stuff omitted
Controller brains;
public void update(){
brains.update(this);
// .. non-behavioral physics stuff omitted
}
public void setController(Controller brains){
this.brains = brains;
}
// methods that will be called by the controller in order to control the entity:
public void attack(){
....
}
public void moveLeft(){
....
}
// ....
}
A PlayerController can read user input and control the entity accordingly, while an AIController would implement a state machine to control the entity. The controllers would use the entity's public interface to control it.
The only doubt I have about this approach is that it forces the entities to offer a lot of public methods to control them, such as moveLeft() and shootMissile().
Conceptually, it doesn't "feel right" that the entity would expose methods like these to the outside world, when it should be it's own job to control itself. Just like it isn't possible to control a human's legs or heart from the outside.
So my question is: what do you think of this approach? Can you recommend a better one? How is this often done in games?