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 'conceptually' 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. Feels like it breaks encapsulation.
So my question is: what do you think of this approach? Can you recommend a better one? How is this often done in games?