Saya pikir semacam solusi yang kuat akan pergi dengan cara berorientasi objek.
Bergantung pada pencapaian seperti apa yang ingin Anda dukung, Anda perlu cara untuk menanyakan keadaan saat ini dari permainan Anda dan / atau sejarah tindakan / peristiwa yang dibuat oleh objek permainan (seperti pemain).
Katakanlah Anda memiliki kelas Prestasi dasar seperti:
class AbstractAchievement
{
GameState& gameState;
virtual bool IsEarned() = 0;
virtual string GetName() = 0;
};
AbstractAchievement
memegang referensi ke kondisi permainan. Ini digunakan untuk menanyakan hal-hal yang sedang terjadi.
Kemudian Anda membuat implementasi konkret. Mari kita gunakan contoh Anda:
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;
}
};
Maka terserah Anda untuk memutuskan kapan harus memeriksa menggunakan IsEarned()
metode. Anda dapat memeriksa di setiap pembaruan game.
Cara yang lebih efisien adalah, misalnya, memiliki semacam manajer acara. Dan kemudian mendaftarkan peristiwa (seperti PlayerHasSlicedSomethingEvent
atau PlayerGotInvicibleEvent
atau hanya PlayerStateChanged
) ke metode yang akan mengambil pencapaian dalam parameter. Contoh:
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;
sama denganreturn (...)