Ryan Peschel
Ryan Peschel

Reputation: 11986

How to convert from mouse coordinates to world coordinates in a Javascript canvas game?

I'm developing a simple top-down game in Javascript using the 2d Canvas API. At the moment, I have the camera always centered on the player, such that they are always in the center of the screen. This is done like this:

let camX = -player.pos.x + this.canvas.width / 2;
tet camY = -player.pos.y + this.canvas.height / 2;

this.context.translate(camX, camY);

And it seems to work just fine. My issue comes in when I want to have the player click somewhere on the screen and have that click be translated into world coordinates. That is, if the player clicks somewhere, I should be able to use the relative mouse position combined with the camera transformation to obtain the world coordinates of the click.

I thought it would as simple as the following:

let worldX = -camX + input.mousePosition.x;
let worldY = -camY + input.mousePosition.y;

But it doesn't seem to be working. If I was using a normal camera object I would just take the inverse matrix I think, but this is just a simple canvas, so I'm not sure if I can do that in this case.

Upvotes: 3

Views: 824

Answers (1)

Ryan Peschel
Ryan Peschel

Reputation: 11986

I figured it out. It's because I was using zoom, which was throwing off the calculation. I'm not sure how to do it manually, but I found out that the canvas has matrix transform and inverse functions, so I created these two functions, which seem to work:

static getWorldCoordsFromRelative(ctx: any, position: Vec2) {
  let matrix = ctx.getTransform();
  var imatrix = matrix.invertSelf();

  return new Vec2(position.x * imatrix.a + position.y * imatrix.c + imatrix.e,
                  position.x * imatrix.b + position.y * imatrix.d + imatrix.f);
}

static getRelativeCoordsFromWorldCoords(ctx: any, position: Vec2) {
  let matrix = ctx.getTransform();
  
  return new Vec2(position.x * matrix.a + position.y * matrix.c + matrix.e,
                  position.x * matrix.b + position.y * matrix.d + matrix.f);
}

Upvotes: 4

Related Questions