Achievement Popup Component - UQdeco2800/2022-studio-1 GitHub Wiki

Page Navigation

Jump to a section or return to Achievement Summary here!

Summary

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.

Technical

UML

Astah - Fig. 1

Design

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.

Implementation

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.

Testing

Game play testing popup notification. The notifcation includes a title,description and badge of the achievement made.

Back to Achievement Summary

⚠️ **GitHub.com Fallback** ⚠️