// Общие константы для редактора и плеера const CELL_SIZE = 30; const GRID_COLOR = '#dee2e6'; const COLORS = { 0: '#f8f9fa', // Дорога 1: '#6c757d', // Камень 2: '#e3f2fd', // Снег 3: '#b3e5fc', // Лёд 4: '#fff3cd', // Чекпоинт 5: '#d4edda' // Старт }; // Общие функции для работы с canvas function drawGrid(ctx, width, height) { ctx.strokeStyle = GRID_COLOR; ctx.lineWidth = 1; // Вертикальные линии for (let x = 0; x <= width; x++) { ctx.beginPath(); ctx.moveTo(x * CELL_SIZE, 0); ctx.lineTo(x * CELL_SIZE, height * CELL_SIZE); ctx.stroke(); } // Горизонтальные линии for (let y = 0; y <= height; y++) { ctx.beginPath(); ctx.moveTo(0, y * CELL_SIZE); ctx.lineTo(width * CELL_SIZE, y * CELL_SIZE); ctx.stroke(); } } function drawCells(ctx, map, width, height) { // Рисуем ячейки for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const cellType = map[y][x]; ctx.fillStyle = COLORS[cellType]; ctx.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE); } } } function drawMarkers(ctx, map, width, height) { // Рисуем маркеры для чекпоинтов и старта ctx.font = 'bold 16px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { if (map[y][x] === 4) { ctx.fillStyle = '#856404'; ctx.fillText('C', x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2); } else if (map[y][x] === 5) { ctx.fillStyle = '#155724'; ctx.fillText('S', x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2); } } } } function validateMap(data) { if (!data.map || !Array.isArray(data.map)) { throw new Error('Неверный формат: отсутствует массив map'); } const newMap = data.map; // Валидация if (!newMap.every(row => Array.isArray(row))) { throw new Error('Неверный формат: map должен быть двумерным массивом'); } const newHeight = newMap.length; const newWidth = newMap[0].length; if (newHeight < 5 || newHeight > 100 || newWidth < 5 || newWidth > 100) { throw new Error('Размеры карты должны быть от 5 до 100'); } if (!newMap.every(row => row.length === newWidth)) { throw new Error('Все строки должны иметь одинаковую длину'); } // Проверка значений ячеек const validValues = [0, 1, 2, 3, 4, 5]; for (let y = 0; y < newHeight; y++) { for (let x = 0; x < newWidth; x++) { if (!validValues.includes(newMap[y][x])) { throw new Error(`Недопустимое значение ячейки: ${newMap[y][x]} на позиции [${y}][${x}]`); } } } return { map: newMap, width: newWidth, height: newHeight }; } function findStartPosition(map, width, height) { for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { if (map[y][x] === 5) { return { x, y }; } } } return null; }