Найти, какая плитка была нажата в изометрической, шахматной системе столбцов


Моя сетка

tileWidth = 64px
tileHeight = 128px

(само изображение 128px, хотя фактический Алмаз 32px высотой и 64px шириной)

Введите описание изображения здесь

Как вы можете видеть, у меня есть шахматная сетка; однако я потратил последние два часа, пытаясь придумать систему, в которой я мог бы взять координаты мыши относительно холста и выяснить, какая плитка была нажата (очевидно, в пределах ромбовидного поля).

Например, если я нажму tile 21, 26 - Как я буду вычислять это есть в программе?

Любые указатели, чтобы заставить работать в правильном направлении, будут высоко оценены. Спасибо!

1 3

1 ответ:

Если вы знаете положение центра ячейки, что, конечно, вы делаете, так как они визуализируются, вы просто нормализуете координату относительно ячейки, чтобы узнать, находится ли она внутри:

var dx = Math.abs(x - cellCenterX),
    dy = Math.abs(y - cellCenterY);

if (dx / (cellWidth * 0.5) + dy / (cellHeight * 0.5) <= 1) { /* is inside */ };

Вот полная демонстрация:

var cw = 64,
    ch = 32,
    cells = [],
    maxH = 10,
    maxV = 5,
    toggle = true,
    
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext('2d');

// Using a cell object for convenience here:
function Cell(posX, posY, x, y, w, h) {
  this.posX = posX;            // some id....
  this.posY = posY;            // some id....
  this.x = x;                  // cells top position
  this.y = y;
  this.w = w;                  // width and height of cell
  this.h = h;
  this.centerX = x + w * 0.5;  // abs. center of cell
  this.centerY = y + h * 0.5;
}

// draw this cell:
Cell.prototype.render = function(ctx, color) {
  ctx.beginPath();
  ctx.moveTo(this.centerX, this.y);
  ctx.lineTo(this.x + this.w, this.centerY);
  ctx.lineTo(this.centerX, this.y+this.h);
  ctx.lineTo(this.x, this.centerY);
  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();
  ctx.strokeStyle = "#000";
  ctx.stroke();
};

// check if x/y is inside this cell
Cell.prototype.isInCell = function(x, y) {

  var dx = Math.abs(x - this.centerX),
      dy = Math.abs(y - this.centerY);

  return (dx / (this.w * 0.5) + dy / (this.h * 0.5) <= 1);
};

// generate cell map
for(var y = 0; y < maxV; y++) {
  var dltX = toggle ? 0 : -cw * 0.5,
      dltY = -ch * 0.5 * y;
  
  toggle = !toggle;
  
  for(var x = 0; x < maxH; x++) {
      var c = new Cell(x, y, x * cw + dltX, y * ch + dltY, cw, ch);
      cells.push(c);
      c.render(ctx, "#9f0"); // green bg
  }
}

// test by clicking in cell
canvas.onclick = function(e) {
  
  var r = canvas.getBoundingClientRect(),
      x = e.clientX - r.left,
      y = e.clientY - r.top,
      i = 0, cell;
  
  for(; cell = cells[i]; i++) {
    if (cell.isInCell(x, y)) {
      cell.render(ctx, "#f00"); // red bg if inside
      out.innerHTML = "Cell pos: (" + cell.posX + "," + cell.posY + ") X: " + cell.x + " Y: " + cell.y;
      break;
    }
  }
};
<canvas id=canvas width=500 height=100></canvas><br>
<output id=out></output>