113 lines
4.2 KiB
JavaScript
113 lines
4.2 KiB
JavaScript
// ==================== МИНИКАРТА ====================
|
|
import { state } from '../core/state.js';
|
|
import { BLOCKS } from '../data/blocks.js';
|
|
import { getBlock } from '../world/world-storage.js';
|
|
import { playSound } from '../audio/sound-engine.js';
|
|
import { isNight } from '../entities/mob-ai.js';
|
|
|
|
const minimapWrap = document.getElementById('minimapWrap');
|
|
const minimapCanvas = document.getElementById('minimap');
|
|
const minimapCtx = minimapCanvas.getContext('2d');
|
|
|
|
// Цвета блоков для миникарты (по 1 пикселю на блок)
|
|
const MINIMAP_COLORS = {
|
|
grass: '#4a8c2a', dirt: '#6b3410', stone: '#6a6a6a', sand: '#d4b84a',
|
|
gravel: '#888', clay: '#5a9ad4', wood: '#a63d00', planks: '#c46a10',
|
|
leaves: '#2a8a3a', glass: '#aaddee', water: '#2980b9', coal: '#1a1a2a',
|
|
copper_ore: '#a05535', iron_ore: '#b0b0b0', gold_ore: '#d4a017',
|
|
diamond_ore: '#0090d0', brick: '#8a2010', tnt: '#c02020',
|
|
campfire: '#d08020', torch: '#d0a020', bedrock: '#1a1a1a',
|
|
flower: '#d03050', bed: '#c03060', ladder: '#a04000', boat: '#6b3410'
|
|
};
|
|
|
|
export function initMinimap() {
|
|
document.getElementById('mapToggle').onclick = () => {
|
|
playSound('click');
|
|
state.minimapOpen = !state.minimapOpen;
|
|
minimapWrap.style.display = state.minimapOpen ? 'block' : 'none';
|
|
};
|
|
}
|
|
|
|
export function renderMinimap() {
|
|
if (!state.minimapOpen) return;
|
|
const mW = minimapCanvas.width;
|
|
const mH = minimapCanvas.height;
|
|
const scale = 2; // пикселей на блок
|
|
const TILE = state.TILE;
|
|
const player = state.player;
|
|
|
|
// Область карты — центрирована на игроке
|
|
const pGX = Math.floor(player.x / TILE);
|
|
const pGY = Math.floor(player.y / TILE);
|
|
const viewW = Math.floor(mW / scale);
|
|
const viewH = Math.floor(mH / scale);
|
|
const startGX = pGX - Math.floor(viewW / 2);
|
|
const startGY = pGY - Math.floor(viewH / 2);
|
|
|
|
// Очищаем
|
|
minimapCtx.fillStyle = isNight() ? '#070816' : '#87CEEB';
|
|
minimapCtx.fillRect(0, 0, mW, mH);
|
|
|
|
// Рисуем блоки
|
|
const imgData = minimapCtx.createImageData(mW, mH);
|
|
const data = imgData.data;
|
|
|
|
for (let dx = 0; dx < viewW; dx++) {
|
|
for (let dy = 0; dy < viewH; dy++) {
|
|
const gx = startGX + dx;
|
|
const gy = startGY + dy;
|
|
const b = getBlock(gx, gy);
|
|
if (!b || b.dead || b.t === 'air') continue;
|
|
|
|
const color = MINIMAP_COLORS[b.t];
|
|
if (!color) continue;
|
|
|
|
// Парсим hex цвет
|
|
const r = parseInt(color.slice(1, 3), 16);
|
|
const g = parseInt(color.slice(3, 5), 16);
|
|
const bl = parseInt(color.slice(5, 7), 16);
|
|
|
|
// Заполняем scale x scale пикселей
|
|
for (let sx = 0; sx < scale; sx++) {
|
|
for (let sy = 0; sy < scale; sy++) {
|
|
const px = dx * scale + sx;
|
|
const py = dy * scale + sy;
|
|
if (px >= mW || py >= mH) continue;
|
|
const idx = (py * mW + px) * 4;
|
|
data[idx] = r;
|
|
data[idx + 1] = g;
|
|
data[idx + 2] = bl;
|
|
data[idx + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
minimapCtx.putImageData(imgData, 0, 0);
|
|
|
|
// Игрок — белый пиксель по центру
|
|
minimapCtx.fillStyle = '#fff';
|
|
minimapCtx.fillRect(Math.floor(mW / 2) - 2, Math.floor(mH / 2) - 2, 4, 4);
|
|
|
|
// Другие игроки — жёлтые точки
|
|
for (const [sid, p] of state.otherPlayers) {
|
|
const dx = Math.floor(p.x / TILE) - startGX;
|
|
const dy = Math.floor(p.y / TILE) - startGY;
|
|
if (dx >= 0 && dx < viewW && dy >= 0 && dy < viewH) {
|
|
minimapCtx.fillStyle = '#f1c40f';
|
|
minimapCtx.fillRect(dx * scale - 1, dy * scale - 1, 3, 3);
|
|
}
|
|
}
|
|
|
|
// Мобы — красные (враждебные) / зелёные (животные)
|
|
const allMobsForMap = state.isMultiplayer ? Array.from(state.serverMobs.values()) : state.mobs;
|
|
for (const m of allMobsForMap) {
|
|
const dx = Math.floor(m.x / TILE) - startGX;
|
|
const dy = Math.floor(m.y / TILE) - startGY;
|
|
if (dx >= 0 && dx < viewW && dy >= 0 && dy < viewH) {
|
|
const hostile = m.kind === 'zombie' || m.kind === 'creeper' || m.kind === 'skeleton';
|
|
minimapCtx.fillStyle = hostile ? '#e74c3c' : '#2ecc71';
|
|
minimapCtx.fillRect(dx * scale, dy * scale, 2, 2);
|
|
}
|
|
}
|
|
} |