Reputation: 21136
I have a Player class... He needs access to components inside PlayerStateFlying and PlayerStateHit classes so I inherited from them...
class PlayerStateFlying
{
// Includes a function that sets Player::currentState = something
}
class PlayerStateHit
{
// Includes a function that sets Player::currentState = something
}
class Player : public PlayerStateFlying,
public PlayerStateHit
{
public:
STATE currentState; // Needs to be accessed by the State classes
}
Problem is, my State classes need access to one of Player's properties
How do I go about solving this problem?
---------EDIT-----------
So should it be something like this? P.S I can't quite get it to work
class IBaseStates
{
public:
STATE currentState;
}
class PlayerStateFlying : public IBaseStates
{
// Includes a function that sets IBaseStates::currentState = something
}
class PlayerStateHit : public IBaseStates
{
// Includes a function that sets IBaseStates::currentState = something
}
class Player : public IBaseStates
{
// Includes a function that checks what IBaseStates::currentState equals
}
Here is an example of my dilemma:
void Player::ChangeState( STATE state )
{
switch( state )
{
case FLYING:
currentState = FLYING;
break;
case HIT:
currentState = HIT;
break;
}
}
void Player::StateUpdate()
{
switch( currentState )
{
case FLYING:
PlayerStateFlying::Update( );
currentTextureIndex = PlayerStateFlying::current;
break;
case HIT:
PlayerStateHit::Update( );
currentTextureIndex = PlayerStateHit::current;
break;
}
}
void PlayerStateHit::Update( )
{
...
currentState = FLYING;
index = 0;
...
}
Upvotes: 0
Views: 90
Reputation: 916
Do not forget about polymorphism. You don't need to implement any switch
'es.
I think the solution should look like:
class PlayerState {
}
class PlayerStateFlying : public PlayerState {
}
class PlayerStateHit : public PlayerState {
}
Now your Player
class (object) should contain (or access) a state object:
class Player {
protected:
PlayerState *playerState;
public:
void setPlayerState(PlayerState *newState);
}
setPlayerState()
should look like:
Player::setPlayerState(PlayerState *newState) {
playerState = newState;
}
Now you can simply rewrite your methods for the future supporting variety of PlayerState subclasses:
void Player::StateUpdate() {
playerState->Update(); // Polymorphism!
currentTextureIndex = playerState->current;
}
In the next method you can still use a switch if you still really need to store your currentState
variable and use it:
void Player::ChangeState( STATE state ) {
switch( state ) {
case FLYING:
currentState = FLYING;
playerState = new PlayerStateFlying();
break;
case HIT:
currentState = HIT;
playerState = new PlayerStateHit();
break;
}
}
... but there is another -- more convenient solution -- setPlayerState
-- we already have it, but if we still need currentState
enum (or int or whatever) variable, we can simply expand our PlayerState
class (and subclasses) with a new field -- label
:
class PlayerState {
public:
int label;
}
PlayerStateFlying::PlayerStateFlying() {
label = FLYING;
}
PlayerStateHit::PlayerStateHit() {
label = HIT;
}
Now it is possible to:
Player::setPlayerState(PlayerState *newState) {
playerState = newState;
currentState = playerState->label;
}
You can also try with constant fields, that is:
class PlayerState {
public:
const int label;
}
PlayerStateFlying::PlayerStateFlying() : label(FLYING) {};
PlayerStateHit::PlayerStateHit() : label(HIT) {};
Regards.
Upvotes: 2
Reputation: 7961
A player should be the one setting what the current state is. Not the state itself. And the state update function should look something like:
void Player::StateUpdate() {
mCurrentState->update(this);
}
void PlayerHitState(Player * player) {
player->setCurrentState(player->getStateFromListOfAvailableStates(FLYING))
}
A simple state machine should store all the needed states and transitions. Like you can't fly if you are in water or something similar.
Upvotes: 1
Reputation: 28390
Have a common class that stores the State and the information that is needed access to and inherit from it in both Player states.
Upvotes: 0