Mini Map - UQcsse3200/2024-studio-2 GitHub Wiki
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.
There are some features of mini map, including:
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.
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.
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.
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;
}
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
}
}
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);
}
}
}
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();
}
}
@Test
public void testPlayerMiniMapPos() {
Vector2 playerMiniMapPos = miniMapDisplay.transferToMiniMapPos(player);
assertEquals(new Vector2(miniMapDisplay.miniMapSize/2, miniMapDisplay.miniMapSize/2), playerMiniMapPos);
}
@Test
public void testEnemyOneMiniMapPos() {
Vector2 enemyOneMiniMapPos = miniMapDisplay.transferToMiniMapPos(enemy1);
assertEquals(new Vector2(-150, -150), enemyOneMiniMapPos);
}
@Test
public void testEnemyTwoMiniMapPos() {
Vector2 enemyTwoMiniMapPos = miniMapDisplay.transferToMiniMapPos(enemy2);
assertEquals(new Vector2(250, 250), enemyTwoMiniMapPos);
}