The basic idea comes from the map of a game. According to the my code review, the map is a full-page canvas. I have no problem with drawing images on canvas. My question is how to detect map houses and update the canvas or even add click ability to it.
I have attached a GIF and HTML code from the original game to better understand my request.
<div id="canvasBorder"><canvas id="canvasMap"></canvas></div>
Okay, This is my code. It’s simple. I have drawn the map houses according to the main image which is large on the canvas.
function onClick2() {
const imagePath = '/lobby/map.png';
//Image Positions and Width/Height
const array = [
{ x: 1764, y: 1104, w: 126, h: 84 },
{ x: 0, y: 1188, w: 126, h: 84 },
{ x: 126, y: 1188, w: 126, h: 84 },
{ x: 2090, y: 340, w: 126, h: 68 },
{ x: 126, y: 1188, w: 126, h: 84 },
];
if (canvasRef?.current) {
let x = canvasRef?.current.getContext('2d');
let img = new Image();
img.src = path;
//Draw Map Blocks
//Here I deleted the extra codes, I just wanted to show that it was done this way.
if (x) {
x.drawImage(
img,
array[3].x,
array[3].y,
array[3].w,
array[3].h,
0,
0,
array[3].w,
array[3].h
);
}
}
}
Here I need your guidance to understand the implementation trick. Here we need to recognize the mouse movement on the image or we need a number of squares that are rotated and have the image and work with the isPointInPath function.
If we proceed with the second way that I mentioned, to draw the squares, we need rotate(-0.25 * Math.PI);
2
Answers
I suggest looking into JavaScript events.
The HTML canvas doesn’t have any fancy input handlers, it’s just for drawing. But we can relatively easily listen for mousemove and click events to interact with the canvas.
Then you can take the
clientX
andclientY
properties and use them to calculate which tile on the canvas the mouse intersects with.If the canvas is not positioned at the top left, we can get the bounding client rect and subtract the
clientLeft
andclientTop
properties of the canvas from the mouse coordinates to get the mouse position relative to the canvas.If we have the coordinates relative to the canvas it should be as simple as a collision detection, followed by performing a visual change in the canvas.
For the collision detection you can refer to this stackoverflow post and do some research.
You need to track the cursor position with
mousemove
and then do a simple change of basis to translate screen coordinates to game grid coordinates:The cursor’s position
v_C = (x, y)
is in the canonical basis,C
.You have an alternate basis
B
(your 2.5D grid), and its alternate basis vectors in basisC
are:You put them in columns on a matrix
M_BC
:This matrix helps you translate vectors from basis
B
toC
Invert that matrix to get
M_CB
. This matrix helps you translate vectors from basisC
toB
.v_B = M_CB * v_C
Lastly, floor the coordinates. This tells you what cell to select/highlight in the 2.5D grid.
Still:
I’m not a mathematician, so the nomenclature I’m using might be off, specially considering I’m mixing more formal vector/matrix expressions with regular camelCase variable names.
It’s easier to see it than to read it, so, first, watch this: 3Blue1Brown – Change of basis | Chapter 13, Essence of linear algebra.
Here’s a working example:
If you don’t care about pixel-perfect accuracy (e.g. you don’t care whether if a cell has a tree that overflows a bit, covering the one behind, the mouse is not able to recognize being on top of the tree), then you don’t need
isPointInPath
, and you also gain a lot of performance.