Eu acho que um tipo de solução robusta seria seguir o caminho orientado a objetos.
Dependendo do tipo de conquista que você deseja apoiar, você precisa de uma maneira de consultar o estado atual do seu jogo e / ou o histórico de ações / eventos que os objetos do jogo (como o jogador) fizeram.
Digamos que você tenha uma classe base de Conquistas, como:
class AbstractAchievement
{
GameState& gameState;
virtual bool IsEarned() = 0;
virtual string GetName() = 0;
};
AbstractAchievementmantém uma referência ao estado do jogo. É usado para consultar as coisas que estão acontecendo.
Então você faz implementações concretas. Vamos usar seus exemplos:
class MasterSlicerAchievement : public AbstractAchievement
{
string GetName() { return "Master Slicer"; }
bool IsEarned()
{
Action lastAction = gameState.GetPlayerActionHistory().GetAction(0);
Action previousAction = gameState.GetPlayerActionHistory().GetAction(1);
if (lastAction.GetType() == ActionType::Slice &&
previousAction.GetType() == ActionType::Slice &&
lastAction.GetObjectType() == ObjectType::Watermelon &&
previousAction.GetObjectType() == ObjectType::Strawberry)
return true;
return false;
}
};
class InvinciblePipeRiderAchievement : public AbstractAchievement
{
string GetName() { return "Invincible Pipe Rider"; }
bool IsEarned()
{
if (gameState.GetLocationType(gameState.GetPlayerPosition()) == LocationType::OVER_PIPE &&
gameState.GetPlayerState() == EntityState::INVINCIBLE)
return true;
return false;
}
};
Cabe a você decidir quando verificar usando o IsEarned()método Você pode verificar a cada atualização do jogo.
Uma maneira mais eficiente seria, por exemplo, ter algum tipo de gerente de eventos. E, em seguida, registre eventos (como PlayerHasSlicedSomethingEventou PlayerGotInvicibleEventou simplesmente PlayerStateChanged) em um método que levaria a conquista no parâmetro Exemplo:
class Game
{
void Initialize()
{
eventManager.RegisterAchievementCheckByActionType(ActionType::Slice, masterSlicerAchievement);
// Each time an action of type Slice happens,
// the CheckAchievement() method is invoked with masterSlicerAchievement as parameter.
eventManager.RegisterAchievementCheckByPlayerState(EntityState::INVINCIBLE, invinciblePiperAchievement);
// Each time the player gets the INVINCIBLE state,
// the CheckAchievement() method is invoked with invinciblePipeRiderAchievement as parameter.
}
void CheckAchievement(const AbstractAchievement& achievement)
{
if (!HasAchievement(player, achievement) && achievement.IsEarned())
{
AddAchievement(player, achievement);
}
}
};
if(...) return true; else return false;é o mesmo quereturn (...)