Mini Map - UQcsse3200/2024-studio-2 GitHub Wiki

1. Overview/Description

The Mini Map feature provides players with a visual representation of their current location and surrounding entities in the game world. This feature enhances the player’s navigation by displaying player positions, and enemy locations in a simplified, top-down view.

minimap 3

2. Features

There are some features of mini map, including:

2.1 Dynamic Entity Representation:

The Mini Map visually represents entities in the game world using colorful dots:

  • The green dot represents the player.
  • The red dot represents the small enemies in the map.
  • The large red dot represents the bosses.
  • The purple dot represents the minigame NPCs.
  • The blue dot represents the friendly NPCs.
  • The minimap's background texture will be made to represent the terrain.

2.2 Real-Time Updates

The Mini Map updates in real-time, displaying the movement of the player and other entities:

  • Player and Entity Movement: As the player and other entities move, their positions are updated once per 15 frames on the map. This helps players avoid enemies, locate allies, or navigate towards objectives.
  • Entity Addition/Removal: When entities are added or removed from the game world (e.g., an enemy is defeated, or a new NPC appears), the Mini Map dynamically adjusts to reflect these changes.

2.3 Terrain Visualization (future development)

The background of the Mini Map represents the terrain and environment surrounding the player. When player moves from forest to water area, the terrains will be updated from green to blue texture.

3. Implementation

3.1 Transfer real-world position to mini map's position

When mapping an entity's position to the mini map, the player's coordinates are treated as (0,0), which is the center of the mini map. Therefore, the entity's coordinates are adjusted relative to the player's position. The scaleFactor determines the representation of distance on the mini map: a higher value results in entities appearing farther from the player.

public Vector2 transferToMiniMapPos(Entity entity) {
        Vector2 playerPos = player.getPosition();
        Vector2 entityPos = entity.getPosition();

        Vector2 entityMiniMapPos = new Vector2(
                (entityPos.x - playerPos.x) / scaleFactor * miniMapDiameter,
                (entityPos.y - playerPos.y) / scaleFactor * miniMapDiameter
        );
        entityMiniMapPos.add(miniMapX + (float)  miniMapDiameter / 2,
                miniMapY + (float) miniMapDiameter / 2);

        return entityMiniMapPos;
    }

3.2 Initialize points based on type of entities.

There are five different point types on the mini map, representing different entities: player, enemies, bosses, friendly NPCs, and mini-game NPCs. Each type of point will correspond to the number of entities of that type in the game.

    // Initialize green dots to match the number of player
    public void initializeGreenDotImages() {
        greenDotPointImage = new Image(new Texture("images/minimap/greenDotPoint.png"));
        greenDotPointImage.setSize(15, 15);
        stage.addActor(greenDotPointImage);
    }

    // Initialize red dots to match the number of enemies
    public void initializeRedDotImages() {
        for (int i = 0; i < enemies.size(); i++) {
            Image redDotImage = new Image(new Texture("images/minimap/redDotPoint.png"));
            redDotImage.setSize(10, 10);
            redDotPointImages.add(redDotImage);
            stage.addActor(redDotImage);  // Add the red dot actor to the stage
        }
    }
    /**
     * Initializes blue dot points for the friendly NPCs.
     */
    public void initializeBlueDotImages() {
        for (int i = 0; i < friendlyNPCs.size(); i++) {
            Image blueDotImage = new Image(new Texture("images/minimap/blueDotPoint.png"));
            blueDotImage.setSize(10, 10);
            blueDotPointImages.add(blueDotImage);
            stage.addActor(blueDotImage);  // Add the red dot actor to the stage
        }
    }

    /**
     * Initializes large red dot points for the friendly NPCs.
     */
    public void initializeLargeRedPointImages() {
        for (int i = 0; i < bosses.size(); i++) {
            Image largeRedDotImage = new Image(new Texture("images/minimap/redDotPoint.png"));
            largeRedDotImage.setSize(30, 30);
            largeRedPointImages.add(largeRedDotImage);
            stage.addActor(largeRedDotImage);  // Add the red dot actor to the stage
        }
    }

3.3 Update Points' Position

When the number of entities changes (e.g., an enemy is defeated or a new friendly NPC is added), the mini map will reinitialize the points accordingly. Additionally, the mini map will update the positions of the points relative to the entities and hide any points representing entities that are outside the mini map's range based on their distance from the player.

private void updatePoints(List<Image> pointImages, List<Entity> entities) {
        if (pointImages.size() != entities.size()) {
            if (pointImages.equals(redDotPointImages)) {
                initializeRedDotImages();
            } else if (pointImages.equals(blueDotPointImages)) {
                initializeBlueDotImages();
            } else if (pointImages.equals(largeRedPointImages)) {
                initializeLargeRedPointImages();
            } else if (pointImages.equals(purplePointImages)) {
                initializePurplePointImages();
            }
        }

        for (int i = 0; i < entities.size(); i++) {
            Entity enemy = entities.get(i);
            Vector2 enemyMiniMapPos = transferToMiniMapPos(enemy);

            float distanceFromCenter = Vector2.dst(centerX, centerY, enemyMiniMapPos.x, enemyMiniMapPos.y);
            if (distanceFromCenter <= minimapRadius) {
                pointImages.get(i).setVisible(true);
                pointImages.get(i).setPosition(enemyMiniMapPos.x, enemyMiniMapPos.y);
            } else {
                pointImages.get(i).setVisible(false);
            }
        }
    }

3.4 Update once per frame

Updating the positions of the points every frame can cause a drop in FPS. To address this, an additional frame counter is used. The points on the mini map are updated once every 15 frames, which results in 4 updates per second if the FPS is 60.

    @Override
    public void update() {
        // Update blue point position (player on the minimap)
        Vector2 playerMiniMapPos = transferToMiniMapPos(player);
        greenDotPointImage.setPosition(playerMiniMapPos.x, playerMiniMapPos.y);
        frameCount++;
        if (frameCount % 15 == 0) {
            updateAllPoints();
        }
    }

4. UML

image

5. Test Cases

5.1 Test Player Position In Mini Map

    @Test
    public void testPlayerMiniMapPos() {
        Vector2 playerMiniMapPos = miniMapDisplay.transferToMiniMapPos(player);
        assertEquals(new Vector2(miniMapDisplay.miniMapSize/2, miniMapDisplay.miniMapSize/2), playerMiniMapPos);
    }

5.2 Test Enemy1 Position In Mini Map

    @Test
    public void testEnemyOneMiniMapPos() {
        Vector2 enemyOneMiniMapPos = miniMapDisplay.transferToMiniMapPos(enemy1);
        assertEquals(new Vector2(-150, -150), enemyOneMiniMapPos);
    }

5.3 Test Enemy2 Position In Mini Map

    @Test
    public void testEnemyTwoMiniMapPos() {
        Vector2 enemyTwoMiniMapPos = miniMapDisplay.transferToMiniMapPos(enemy2);
        assertEquals(new Vector2(250, 250), enemyTwoMiniMapPos);
    }
⚠️ **GitHub.com Fallback** ⚠️