Achievement Popup Component - UQdeco2800/2022-studio-1 GitHub Wiki
Jump to a section or return to Achievement Summary here!
The purpose of the AchievementPopupComponent
is to provide feedback when a player makes an achievement during game play. The popup briefly appears on the screen on top centre where the player can see it and disappears after 5 seconds.
Astah - Fig. 1
The component is designed to be losely coupled with the rest of the game. It can be attached to the main game screen in the form of the decorator pattern. This makes it versatile to be attached to any other screen that needs it. By design it uses a priority queue to queue all incoming achievements. Meaning only one achievement notification can be shown at any one time others are queued and are displayed later when the screen area becomes available again. Designing it this way gives the player time to observe their achievement before it's replace by another. So if the user makes successive achievements in one go they don't conflict.
The very first thing the component does is upon create
. It connects event listeners on AchievementHandler
service so that it can receive
events when an achievement is made. It then sets up the queue.
/**
* Initialises component.
* Connects to the player achievements event
*/
@Override
public void create() {
super.create();
this.isPopupActive = false;
popupQueue = new LinkedList<>();
ServiceLocator.getAchievementHandler().getEvents()
.addListener(AchievementHandler.EVENT_STAT_ACHIEVEMENT_MADE, this::onAchievementMade);
ServiceLocator.getAchievementHandler().getEvents().addListener(AchievementHandler.EVENT_ACHIEVEMENT_MADE, this::onAchievementMade);
}
When an achievement is made it is added to the queue for display:
private void onAchievementMade(Achievement achievement) {
this.popupQueue.add(achievement);
}
Instead of drawing to the badge it adds the notification to the stage.
It has to make several decisions based on the type of achievement being displayed.
Stat achievements have a format string that their description comes from. This
format string must be filled. When the popup should no longer be active, the actors (UI elements) are removed
from the stage and then if the queue is not empty the next achievement is fetched until there's no more to display.
System.currentTimeMillis
is used to record the last time the popup was displayed so it can be determined if the popup has timed out.
There might have been a better way to do this, maybe using the game timer but this works.
@Override
protected void draw(SpriteBatch batch) {
if (!popupQueue.isEmpty() && !isPopupActive) {
var achievement = popupQueue.poll();
clearActors();
if (achievement.isStat()) {
buildActors(achievement.getAchievementType().getPopupImage(),
achievement.getName(), achievement.getDescription().formatted(achievement.getTotalAchieved()));
} else {
buildActors(achievement.getAchievementType().getPopupImage(),
achievement.getName(), achievement.getDescription());
}
addActors();
lastPopupTime = System.currentTimeMillis();
isPopupActive = true;
}
if(isPopupActive && shouldHidePopup()) {
clearActors();
isPopupActive = false;
}
}
For more technical details about implementation please see the JavaDoc.
Game play testing popup notification. The notifcation includes a title,description and badge of the achievement made.