Anyone know of a design pattern for Achievements ?
I assume some sort of static class in the application that gets sent messages … ideas/thoughts/sample code ?
I don’t like the idea of littering the code with checks all over the place for different types of achievements.
I’m currently working on adding stats to my game. A singleton receives a “GameStats” object at the end of each games which contains game duration, score and other stats. It updates global stats and saves them. I could put achievement management in there as well so all conditions are checked in a single place.
However, if I go for achievements, I’ll probably look into third party libs like scoreloop.
if you want to use it for WordHero I don’t think scoreloop will work because their servers are very slow sometime and it’s better to keep everything under your control.
I don’t know which Design Pattern is the right one for you but you can check the most common one here:
I do checks at specific points in the app. For Shifting Letters I make checks: When a word is found, when the game ends and when the global stats are updated.
In my achievement/stats manager I have a collection for each checkpoint which takes conditions to check against the type of data that is submitted at each point (condition collection at game over looks like: Condition<Statistics, ?>, so it’s a collection of conditions that check the Statistics object against whatever the subclass wants to check it against). When the checkpoint is called all conditions in the collection are tested.
When a word is found the data submitted to be checked is a String (the word that was found), game over is a Statistics object and global stats updated is a Collection<Statistics>.
Conditions each belong to an achievement, they have a reference to the achievement they belong to. When the condition is checked, if the condition in met, the achievement is notified so it can check if all its conditions have been met.
Conditions all subclass Condition<T,S> where T is the type of the data being submitted and S is the data type of the condition. They have to implement a method checkCondition(T againstThisCheckPointData) where they check whatever the subclasses S is against T.
PointsSingleGameCondition extends Condition<Statistics, Integer>
Creating a PointsSingleGameCondition p = new PointsSingleGameCondition(condtionValue);
The check for this one just looks to see if the points scored in the game were greater than conditionValue. The subclass implements checkCondition(T againstThisCheckPointData) to perform the check.
There’s more to it than that but that’s the basic overview. How it’s all stored and linked together is quite frankly a mess at the moment and is one of the main focuses of my current rewrite along with generalising the whole thing to make it easier to plug in to further games. Also splitting achievements and stats into independent systems to improve separation of concerns. Generally trying to build it into a library which I can drop in and have running quickly.
Well, this was the point of me asking for a design pattern on how to do this… Because spaghetti code all over the place is the easy way to do it… until you add more and more achievements, it becomes a major PITA
You don’t have to follow a design pattern to avoid bad code. The system as a whole is too large and complicated for a single design pattern to fit. You aren’t going to get a “just implement this pattern” answer. I can merrily add Achievements all day within the constraints I originally set for my system. If you want a highly generic system that will let you compare anything to anything anywhere it gets quite a bit more complicated pretty quickly.
When I said “stored and linked together” “mess” I was talking about the code that persists and restores the data with json. Even then it is neither “spaghetti” nor “all over the place” it just isn’t very elegant.