Minimap
The minimap is an essential element that visually represents the player’s position and the surrounding environment during gameplay. It allows players to easily check their position on the overall map and identify the location of enemies or objectives. In this section, we will explore how to implement a minimap in Redbrick Studio.
Components of the Minimap
To construct a minimap, the following key elements are necessary:
- Player Position: The current position of the player must be displayed on the minimap.
- Enemy Position: The positions of nearby enemies or NPCs should be indicated to help players assess the situation.
- Minimap Rotation: The minimap should rotate according to the player’s line of sight, providing a more intuitive navigation experience.
Steps
Minimap Initialization
Add the minimap, enemy, and player GUI to the scene and create the necessary objects.
class Minimap {
constructor() {
this.enemyGUI = GUI.getObject("ENEMY");
this.miniMap = GUI.getObject("minimap");
this.miniMap.material.rotation = 0; // Initial rotation angle
}
}
Updating Player Position
Update the elements of the minimap based on the player’s position.
moveMinimapUI() {
const playerPosition = PLAYER.position;
this.updateEnemyMinimap(this.enemyGUI, enemy, playerPosition);
}
Calculating Enemy Position
Calculate the relative position to display the enemy’s location on the minimap.
updateEnemyMinimap(enemyGui, enemy, playerPosition) {
const { x: playerPosX, z: playerPosZ } = playerPosition;
const enemyPosX = -enemy.position.x + playerPosX;
const enemyPosZ = enemy.position.z - playerPosZ;
const { rotatedX, rotatedZ } = this.calculateRotatedPosition(enemyPosX, enemyPosZ);
this.setEnemyGuiPosition(enemyGui, rotatedX, rotatedZ);
}
Minimap Rotation
Rotate the minimap according to the player’s line of sight.
const forwardDirection = new THREE.Vector3(0, 0, -1).applyEuler(PLAYER.rotation);
GLOBAL.minimap.miniMap.material.rotation = -Math.atan2(forwardDirection.x, forwardDirection.z);
Complete Code
const enemy = WORLD.getObject("Enemy");
class Minimap {
constructor() {
this.enemyGUI = GUI.getObject("ENEMY");
this.miniMap = GUI.getObject("minimap");
this.miniMap.material.rotation = 0; // Initial rotation angle
this.previousRotationY = 0; // Initialize previous rotation value
}
moveMinimapUI() {
const playerPosition = PLAYER.position;
// Update enemy position on minimap
this.updateEnemyMinimap(this.enemyGUI, enemy, playerPosition);
}
updateEnemyMinimap(enemyGui, enemy, playerPosition) {
const { x: playerPosX, z: playerPosZ } = playerPosition;
const enemyPosX = -enemy.position.x + playerPosX;
const enemyPosZ = enemy.position.z - playerPosZ;
const { rotatedX, rotatedZ } = this.calculateRotatedPosition(enemyPosX, enemyPosZ);
this.setEnemyGuiPosition(enemyGui, rotatedX, rotatedZ);
}
calculateRotatedPosition(posX, posZ) {
const scaledX = posX / 100;
const scaledZ = posZ / 100;
const rotationY = this.miniMap.material.rotation; // Y-axis rotation
// Reflect Y-axis rotation
const rotatedX = scaledX * Math.cos(rotationY) - scaledZ * Math.sin(rotationY);
const rotatedZ = scaledX * Math.sin(rotationY) + scaledZ * Math.cos(rotationY);
return { rotatedX, rotatedZ };
}
setEnemyGuiPosition(gui, rotatedX, rotatedZ) {
const radius = 0.4;
const distance = Math.sqrt(rotatedX * rotatedX + rotatedZ * rotatedZ);
if (distance > radius) {
const scale = radius / distance;
gui.position.x = -rotatedX * scale;
gui.position.y = -rotatedZ * scale;
} else {
gui.position.x = -rotatedX;
gui.position.y = -rotatedZ;
}
}
}
GLOBAL.minimap = new Minimap();
function Start() {
// Initialization tasks
}
function Update(dt) {
// Update minimap rotation
const forwardDirection = new THREE.Vector3(0, 0, -1).applyEuler(PLAYER.rotation);
GLOBAL.minimap.miniMap.material.rotation = -Math.atan2(forwardDirection.x, forwardDirection.z); // Rotate based on direction
GLOBAL.minimap.moveMinimapUI();
}