Creo que una solución sólida sería ir orientado a objetos.
Dependiendo del tipo de logro que desee apoyar, necesita una forma de consultar el estado actual de su juego y / o el historial de acciones / eventos que han realizado los objetos del juego (como el jugador).
Digamos que tiene una clase de Logro base como:
class AbstractAchievement
{
GameState& gameState;
virtual bool IsEarned() = 0;
virtual string GetName() = 0;
};
AbstractAchievement
tiene una referencia al estado del juego. Se utiliza para consultar las cosas que están sucediendo.
Luego haces implementaciones concretas. Usemos sus ejemplos:
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;
}
};
Entonces depende de usted decidir cuándo verificar utilizando el IsEarned()
método. Puedes consultar cada actualización del juego.
Una forma más eficiente sería, por ejemplo, tener algún tipo de administrador de eventos. Y luego registre eventos (como PlayerHasSlicedSomethingEvent
o PlayerGotInvicibleEvent
simplemente PlayerStateChanged
) en un método que tome el logro en parámetro. Ejemplo:
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;
es lo mismo quereturn (...)