Penso che una sorta di soluzione robusta sarebbe quella di orientarsi verso gli oggetti.
A seconda del tipo di obiettivo che desideri supportare, hai bisogno di un modo per interrogare lo stato corrente del tuo gioco e / o la storia delle azioni / eventi che gli oggetti del gioco (come il giocatore) hanno fatto.
Supponiamo che tu abbia una classe di Achievement di base come:
class AbstractAchievement
{
GameState& gameState;
virtual bool IsEarned() = 0;
virtual string GetName() = 0;
};
AbstractAchievement
contiene un riferimento allo stato del gioco. È usato per interrogare le cose che stanno accadendo.
Quindi esegui implementazioni concrete. Usiamo i tuoi esempi:
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;
}
};
Quindi spetta a te decidere quando verificare utilizzando il IsEarned()
metodo. Puoi controllare ad ogni aggiornamento del gioco.
Un modo più efficiente sarebbe, ad esempio, avere un qualche tipo di gestore di eventi. Quindi registra gli eventi (come PlayerHasSlicedSomethingEvent
o PlayerGotInvicibleEvent
o semplicemente PlayerStateChanged
) su un metodo che porterebbe il risultato nel parametro. Esempio:
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;
è lo stesso direturn (...)