合并网格中的六边形

问题描述 投票:0回答:1

我有一个六边形网格,我正在使用具有不同类型值和相应颜色的 HTML 画布绘制。我想将与其他六边形相邻的相同类型的六边形组合起来。这是我当前的功能:

drawGrid() {

        lineCtx.clearRect(0, 0, canvas.width, canvas.height);

        const size = mapContainer.zoom * 100;

        const rect = mapContainer.getViewedHexes();

        let hexList = [];

        for (let row = rect.top; row < rect.bottom; row++) {
                
            for (let col = rect.left; col < rect.right; col++) {

                hexList.push({
                    points: hexPoints(hexCenter(size, row, col), size, size),
                    row: row,
                    col: col,
                    type: mapContainer.hexGrid[row][col]
                }); 
                
            }
    
        }

        //Combine the hexes where they neighbour the same type, the way the hexes are drawn is in the odd-r horizontal layout where the odd rows are shoved right.

        hexList.forEach(hex => {
            this.drawPolygon(hex.points, "rgba(255,0,0, 0.4)");
        });

    }

也可以随意批评我的 javascript 代码,因为我还有很多东西要学。

这些是我用来创建十六进制网格的一些函数,如果你想看的话:

function hexPoints(center, height, width) {

    const points = [];

    for (let i = 0 ; i < 6 ; i++) {
        points[i] = hexCorner(center, height / 2, width / 2, i);
    }

    //Point 0 is the top right corner
    //Point 1 is the bottom right corner
    //Point 2 is the bottom middle corner
    //Point 3 is the bottom left corner
    //Point 4 is the top left corner
    //Point 5 is the top middle corner

    return points;

}

function hexCorner(center, height, width, i) {
    const angleDeg = 60 * i - 30;
    const angleRad = Math.PI / 180 * angleDeg;
    const x = center.x + width * Math.cos(angleRad);
    const y = center.y + height * Math.sin(angleRad);
    return { x, y };
}

function hexCenter(size, row, col) {
    
    let offset = 0;

    if (row % 2 === 1) {
        offset = Math.sqrt(3) * size / 4
    }

    const w = Math.sqrt(3) * size / 2;
    const h = 3/2 * size / 2;
    const x = w * col + offset + w / 2 + mapContainer.mapX;
    const y = h * row + h / (3/2) + mapContainer.mapY;

    return {
        x: x,
        y: y
    };

}
javascript html html5-canvas polygon hexagonal-tiles
1个回答
0
投票

所以你想“视觉上”合并?然后简单地跳过抚摸路径。

const ctx = document.querySelector('#grid').getContext('2d');

const TAU = 2 * Math.PI;
const EDGES = 6;

const mapContainer = {
  hexGrid: [
    [0, 1, 1, 1, 0],
    [1, 2, 2, 2, 1],
    [1, 2, 2, 2, 1],
    [1, 1, 2, 1, 1],
    [0, 0, 1, 0, 0]
  ],
  zoom: 0.25,
  getViewedHexes: function() {
    return {
      top: 0,
      left: 0,
      bottom: 5,
      right: 5
    };
  }
};

drawGrid();

// Based on: https://stackoverflow.com/a/72663019/1762224
function drawGrid() {
  const size = Math.floor(mapContainer.zoom * 100);
  const rect = mapContainer.getViewedHexes();
  const dimensions = getDimensions(size);
  const points = hexPoints(size);
  for (let gy = rect.top; gy < rect.bottom - rect.top; gy++) {
    for (let gx = rect.left; gx < rect.right - rect.left; gx++) {
      const color = typeToColor(mapContainer.hexGrid[gy][gx]);
      ctx.fillStyle = color;
      ctx.strokeStyle = color;
      drawPolygon(hexCenter(gx, gy, size), points);
    }
  }
}

function typeToColor(type) {
  switch (type) {
    case 1:
      return 'grey';
    case 2:
      return 'yellow';
    case 0:
    default:
      return 'white';
  }
}

function hexCenter(gx, gy, size) {
  const { grid } = getDimensions(size);
  return {
    x: (gx + 1) * grid.space.x,
    y: (gy + 1) * grid.space.y + (gx % 2 ? grid.offset.y : 0)
  };
}

function drawPolygon(p, points) {
  ctx.setTransform(1, 0, 0, 1, p.x, p.y);
  const [{ x: startX, y: startY }] = points;
  ctx.beginPath();
  ctx.moveTo(startX, startY);
  points.forEach(({ x, y }) => {
    ctx.lineTo(x, y);
  });
  ctx.closePath();
  ctx.stroke();
  ctx.fill();
}

function hexPoints(size, sides = EDGES, points = []) {
  const step = TAU / sides;
  let ang = 0, i = sides;
  while (i--) {
    points.push(toPoint(size * Math.cos(ang), size * Math.sin(ang)));
    ang += step;
  }
  return points;
}

function getDimensions(radius, edges = EDGES) {
  const
    edgeLength = Math.sin(Math.PI / edges) * radius * 2,
    gridSpaceX = radius * 2 - edgeLength * 0.5,
    gridSpaceY = Math.cos(Math.PI / edges) * radius * 2,
    gridOffsetY = gridSpaceY * 0.5;
  return {
    edgeLength,
    grid: {
      space: {
        x: gridSpaceX,
        y: gridSpaceY
      },
      offset: {
        y: gridOffsetY
      }
    }
  };
}

function toPoint(x, y) {
  return ({ x, y });
}
#grid { border: 1px solid #000000; }
<canvas id="grid" width="260" height="260"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.