Find which tile was clicked in an isometric, staggered column system
My grid
tileWidth = 64px
tileHeight = 128px
(the image itself is 128px, although the actual diamond is 32px high and 64px wide)
As you can see, I have a chess grid system; However, I've spent the last two hours trying to think about a system where I can take the mouse coordinates relative to the canvas and figure out which tile was clicked (obviously in the diamond area).
For example, if I clicked tile 21, 26
- how would I figure it out in the program?
Any pointers to work in the right direction are greatly appreciated. Thank!
+3
source to share
1 answer
If you know the center position of a cell, which of course you are doing from the time they are rendered, you simply normalize the coordinate against the cell to see if it is inside:
var dx = Math.abs(x - cellCenterX),
dy = Math.abs(y - cellCenterY);
if (dx / (cellWidth * 0.5) + dy / (cellHeight * 0.5) <= 1) { /* is inside */ };
Here's the complete demo:
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>
+7
source to share