mouse coordinates to grid coordinates within an isometric map
I asked this question on stackoverflow.com first but I got referred to SE Code Review. I closed the original question and posted it here again.
I wrote an algorithm to transform mouse screen coordinates within an isometric map to corresponding coordinates of an underlying 2D-square grid. The algorithm works and I tested it successfully. I wanted to post it here so interested people could maybe check the algorithm and see if I can make any optimizations beyond of what I did already. My goal is to make the algorithm as compact as possible. There maybe are some smart mathematical solutions I didn't think of to save some lines of code or make it faster.
The input data for the rendering of the map is a simple 2D-array like
0,0,0,0
0,0,0,0
0,0,0,0
...
Here is a screenshot of what the map looks like when rendered. It is not really a map right now but more of an outlining of the tiles I will render. The red coordinates are x and y values of the underlying source grid.
It is rendered with a zig-zag approach with an origin outside of the screen (top left). It is rendered row by row from left to right whereby every uneven row is inset by half a tiles width. This is a common approach to avoid having to fill the source 2D-grid with "zombie-data" if one would render it in a diamond approach.
What the algorithm does is:
- the screen is logically divided into square rectangles with a width of my tile width and height of my tile height, i.e. 128px by 64px
- the mouse coordinates are scaled by tile width and tile height and then floored. This determines in which screen rectangle the user clicked
- then the mouse coordinates are compared against the center coordinates of this rectangle
- regarding this result, a right angled triangle is calculated to check if the user clicked within a certain area of the rectangle. I am using the cosine of this triangle to compare against my initial rotation angle of 26,565 (atan of 0.5). This is the angle in which the sides of the rendered rhombi are rotated to achieve a 2:1 ratio of width and height (classic isometric projection for video games).
- regarding on where the user clicked
- the y value is determined from a lower and upper boundary
- the x value is determined based on y being even or uneven
Here is the algorithm (in c++):
//convert all input parameters to double
double mouseXPos = boost::numeric_cast<double>(pMouseXPos);
double mouseYPos = boost::numeric_cast<double>(pMouseYPos);
double tileWidth = boost::numeric_cast<double>(pTileWidth);
double tileHeight = boost::numeric_cast<double>(pTileHeight);
double tileWidthHalf = tileWidth / 2;
double tileHeightHalf = tileHeight / 2;
//calculate y position in screen grid
double mouseTileYPos = mouseYPos / tileHeight;
mouseTileYPos = std::floor(mouseTileYPos);
//calculate center pixel of the determined rectangle
int screenRectCenterX = ((std::floor((mouseXPos / tileWidth))) * tileWidth) + tileWidthHalf;
int screenRectCenterY = (mouseTileYPos * tileHeight) + tileHeightHalf;
//determine lower and upper boundary for y
int minY = boost::numeric_cast<int>(2 * mouseTileYPos);
int maxY = boost::numeric_cast<int>((2 * mouseTileYPos) + 1);
if (mouseYPos >= screenRectCenterY)
{
minY = maxY;
maxY++;
}
//calc triangle sides in pixels
char mouseRectangleSector[2]{};
double opposite;
double adjacent;
if (mouseYPos >= screenRectCenterY)
{
mouseRectangleSector[0] = 'S';
opposite = mouseYPos - screenRectCenterY;
}
else
{
mouseRectangleSector[0] = 'N';
opposite = screenRectCenterY - mouseYPos;
}
if (mouseXPos >= screenRectCenterX)
{
mouseRectangleSector[1] = 'E';
adjacent = (screenRectCenterX + tileWidthHalf) - mouseXPos;
}
else{
mouseRectangleSector[1] = 'W';
adjacent = tileWidthHalf - (screenRectCenterX - mouseXPos);
}
double hypothenuse = std::sqrt(std::pow(opposite, 2) + std::pow(adjacent, 2));
//calculate cos and corresponding angle in rad and deg
double cos = adjacent / hypothenuse;
double angleRad = std::acos(cos);
double angleDeg = angleRad * 180 / PI;
//calculate initial rotation angle in rad and deg
double controlAtan = 0.5;
double controlAngleRad = std::atan(controlAtan);
double controlAngleDeg = controlAngleRad * 180 / PI;
//determine final position for y
if (mouseRectangleSector[0] == 'S')
{
if (angleRad > controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
else
{
if (angleRad < controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
//determine position for x
double mouseTileXPos;
if ((boost::numeric_cast<int>(mouseTileYPos)) % 2 == 0)
{
mouseTileXPos = (mouseXPos + tileWidthHalf) / tileWidth;
}
else
{
mouseTileXPos = mouseXPos / tileWidth;
}
mouseTileXPos = std::floor(mouseTileXPos);
std::cout << "grid coordinates x,y: " << mouseTileXPos << ","
<< mouseTileYPos << std::endl;
As I said, the algorithm works so i don't need help getting it to run. I am looking for help or advice on how to make it more compact (reduce lines of code). Maybe I can get rid of a couple of if statements by doing some more maths. This is really the first time after my graduation I used this kind of maths in programming so there might be some tweaks that can be done.
If there is no one who has an improvement for this, it can also serve as a solution or inspiration for other people.
c++ game
New contributor
add a comment |
I asked this question on stackoverflow.com first but I got referred to SE Code Review. I closed the original question and posted it here again.
I wrote an algorithm to transform mouse screen coordinates within an isometric map to corresponding coordinates of an underlying 2D-square grid. The algorithm works and I tested it successfully. I wanted to post it here so interested people could maybe check the algorithm and see if I can make any optimizations beyond of what I did already. My goal is to make the algorithm as compact as possible. There maybe are some smart mathematical solutions I didn't think of to save some lines of code or make it faster.
The input data for the rendering of the map is a simple 2D-array like
0,0,0,0
0,0,0,0
0,0,0,0
...
Here is a screenshot of what the map looks like when rendered. It is not really a map right now but more of an outlining of the tiles I will render. The red coordinates are x and y values of the underlying source grid.
It is rendered with a zig-zag approach with an origin outside of the screen (top left). It is rendered row by row from left to right whereby every uneven row is inset by half a tiles width. This is a common approach to avoid having to fill the source 2D-grid with "zombie-data" if one would render it in a diamond approach.
What the algorithm does is:
- the screen is logically divided into square rectangles with a width of my tile width and height of my tile height, i.e. 128px by 64px
- the mouse coordinates are scaled by tile width and tile height and then floored. This determines in which screen rectangle the user clicked
- then the mouse coordinates are compared against the center coordinates of this rectangle
- regarding this result, a right angled triangle is calculated to check if the user clicked within a certain area of the rectangle. I am using the cosine of this triangle to compare against my initial rotation angle of 26,565 (atan of 0.5). This is the angle in which the sides of the rendered rhombi are rotated to achieve a 2:1 ratio of width and height (classic isometric projection for video games).
- regarding on where the user clicked
- the y value is determined from a lower and upper boundary
- the x value is determined based on y being even or uneven
Here is the algorithm (in c++):
//convert all input parameters to double
double mouseXPos = boost::numeric_cast<double>(pMouseXPos);
double mouseYPos = boost::numeric_cast<double>(pMouseYPos);
double tileWidth = boost::numeric_cast<double>(pTileWidth);
double tileHeight = boost::numeric_cast<double>(pTileHeight);
double tileWidthHalf = tileWidth / 2;
double tileHeightHalf = tileHeight / 2;
//calculate y position in screen grid
double mouseTileYPos = mouseYPos / tileHeight;
mouseTileYPos = std::floor(mouseTileYPos);
//calculate center pixel of the determined rectangle
int screenRectCenterX = ((std::floor((mouseXPos / tileWidth))) * tileWidth) + tileWidthHalf;
int screenRectCenterY = (mouseTileYPos * tileHeight) + tileHeightHalf;
//determine lower and upper boundary for y
int minY = boost::numeric_cast<int>(2 * mouseTileYPos);
int maxY = boost::numeric_cast<int>((2 * mouseTileYPos) + 1);
if (mouseYPos >= screenRectCenterY)
{
minY = maxY;
maxY++;
}
//calc triangle sides in pixels
char mouseRectangleSector[2]{};
double opposite;
double adjacent;
if (mouseYPos >= screenRectCenterY)
{
mouseRectangleSector[0] = 'S';
opposite = mouseYPos - screenRectCenterY;
}
else
{
mouseRectangleSector[0] = 'N';
opposite = screenRectCenterY - mouseYPos;
}
if (mouseXPos >= screenRectCenterX)
{
mouseRectangleSector[1] = 'E';
adjacent = (screenRectCenterX + tileWidthHalf) - mouseXPos;
}
else{
mouseRectangleSector[1] = 'W';
adjacent = tileWidthHalf - (screenRectCenterX - mouseXPos);
}
double hypothenuse = std::sqrt(std::pow(opposite, 2) + std::pow(adjacent, 2));
//calculate cos and corresponding angle in rad and deg
double cos = adjacent / hypothenuse;
double angleRad = std::acos(cos);
double angleDeg = angleRad * 180 / PI;
//calculate initial rotation angle in rad and deg
double controlAtan = 0.5;
double controlAngleRad = std::atan(controlAtan);
double controlAngleDeg = controlAngleRad * 180 / PI;
//determine final position for y
if (mouseRectangleSector[0] == 'S')
{
if (angleRad > controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
else
{
if (angleRad < controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
//determine position for x
double mouseTileXPos;
if ((boost::numeric_cast<int>(mouseTileYPos)) % 2 == 0)
{
mouseTileXPos = (mouseXPos + tileWidthHalf) / tileWidth;
}
else
{
mouseTileXPos = mouseXPos / tileWidth;
}
mouseTileXPos = std::floor(mouseTileXPos);
std::cout << "grid coordinates x,y: " << mouseTileXPos << ","
<< mouseTileYPos << std::endl;
As I said, the algorithm works so i don't need help getting it to run. I am looking for help or advice on how to make it more compact (reduce lines of code). Maybe I can get rid of a couple of if statements by doing some more maths. This is really the first time after my graduation I used this kind of maths in programming so there might be some tweaks that can be done.
If there is no one who has an improvement for this, it can also serve as a solution or inspiration for other people.
c++ game
New contributor
add a comment |
I asked this question on stackoverflow.com first but I got referred to SE Code Review. I closed the original question and posted it here again.
I wrote an algorithm to transform mouse screen coordinates within an isometric map to corresponding coordinates of an underlying 2D-square grid. The algorithm works and I tested it successfully. I wanted to post it here so interested people could maybe check the algorithm and see if I can make any optimizations beyond of what I did already. My goal is to make the algorithm as compact as possible. There maybe are some smart mathematical solutions I didn't think of to save some lines of code or make it faster.
The input data for the rendering of the map is a simple 2D-array like
0,0,0,0
0,0,0,0
0,0,0,0
...
Here is a screenshot of what the map looks like when rendered. It is not really a map right now but more of an outlining of the tiles I will render. The red coordinates are x and y values of the underlying source grid.
It is rendered with a zig-zag approach with an origin outside of the screen (top left). It is rendered row by row from left to right whereby every uneven row is inset by half a tiles width. This is a common approach to avoid having to fill the source 2D-grid with "zombie-data" if one would render it in a diamond approach.
What the algorithm does is:
- the screen is logically divided into square rectangles with a width of my tile width and height of my tile height, i.e. 128px by 64px
- the mouse coordinates are scaled by tile width and tile height and then floored. This determines in which screen rectangle the user clicked
- then the mouse coordinates are compared against the center coordinates of this rectangle
- regarding this result, a right angled triangle is calculated to check if the user clicked within a certain area of the rectangle. I am using the cosine of this triangle to compare against my initial rotation angle of 26,565 (atan of 0.5). This is the angle in which the sides of the rendered rhombi are rotated to achieve a 2:1 ratio of width and height (classic isometric projection for video games).
- regarding on where the user clicked
- the y value is determined from a lower and upper boundary
- the x value is determined based on y being even or uneven
Here is the algorithm (in c++):
//convert all input parameters to double
double mouseXPos = boost::numeric_cast<double>(pMouseXPos);
double mouseYPos = boost::numeric_cast<double>(pMouseYPos);
double tileWidth = boost::numeric_cast<double>(pTileWidth);
double tileHeight = boost::numeric_cast<double>(pTileHeight);
double tileWidthHalf = tileWidth / 2;
double tileHeightHalf = tileHeight / 2;
//calculate y position in screen grid
double mouseTileYPos = mouseYPos / tileHeight;
mouseTileYPos = std::floor(mouseTileYPos);
//calculate center pixel of the determined rectangle
int screenRectCenterX = ((std::floor((mouseXPos / tileWidth))) * tileWidth) + tileWidthHalf;
int screenRectCenterY = (mouseTileYPos * tileHeight) + tileHeightHalf;
//determine lower and upper boundary for y
int minY = boost::numeric_cast<int>(2 * mouseTileYPos);
int maxY = boost::numeric_cast<int>((2 * mouseTileYPos) + 1);
if (mouseYPos >= screenRectCenterY)
{
minY = maxY;
maxY++;
}
//calc triangle sides in pixels
char mouseRectangleSector[2]{};
double opposite;
double adjacent;
if (mouseYPos >= screenRectCenterY)
{
mouseRectangleSector[0] = 'S';
opposite = mouseYPos - screenRectCenterY;
}
else
{
mouseRectangleSector[0] = 'N';
opposite = screenRectCenterY - mouseYPos;
}
if (mouseXPos >= screenRectCenterX)
{
mouseRectangleSector[1] = 'E';
adjacent = (screenRectCenterX + tileWidthHalf) - mouseXPos;
}
else{
mouseRectangleSector[1] = 'W';
adjacent = tileWidthHalf - (screenRectCenterX - mouseXPos);
}
double hypothenuse = std::sqrt(std::pow(opposite, 2) + std::pow(adjacent, 2));
//calculate cos and corresponding angle in rad and deg
double cos = adjacent / hypothenuse;
double angleRad = std::acos(cos);
double angleDeg = angleRad * 180 / PI;
//calculate initial rotation angle in rad and deg
double controlAtan = 0.5;
double controlAngleRad = std::atan(controlAtan);
double controlAngleDeg = controlAngleRad * 180 / PI;
//determine final position for y
if (mouseRectangleSector[0] == 'S')
{
if (angleRad > controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
else
{
if (angleRad < controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
//determine position for x
double mouseTileXPos;
if ((boost::numeric_cast<int>(mouseTileYPos)) % 2 == 0)
{
mouseTileXPos = (mouseXPos + tileWidthHalf) / tileWidth;
}
else
{
mouseTileXPos = mouseXPos / tileWidth;
}
mouseTileXPos = std::floor(mouseTileXPos);
std::cout << "grid coordinates x,y: " << mouseTileXPos << ","
<< mouseTileYPos << std::endl;
As I said, the algorithm works so i don't need help getting it to run. I am looking for help or advice on how to make it more compact (reduce lines of code). Maybe I can get rid of a couple of if statements by doing some more maths. This is really the first time after my graduation I used this kind of maths in programming so there might be some tweaks that can be done.
If there is no one who has an improvement for this, it can also serve as a solution or inspiration for other people.
c++ game
New contributor
I asked this question on stackoverflow.com first but I got referred to SE Code Review. I closed the original question and posted it here again.
I wrote an algorithm to transform mouse screen coordinates within an isometric map to corresponding coordinates of an underlying 2D-square grid. The algorithm works and I tested it successfully. I wanted to post it here so interested people could maybe check the algorithm and see if I can make any optimizations beyond of what I did already. My goal is to make the algorithm as compact as possible. There maybe are some smart mathematical solutions I didn't think of to save some lines of code or make it faster.
The input data for the rendering of the map is a simple 2D-array like
0,0,0,0
0,0,0,0
0,0,0,0
...
Here is a screenshot of what the map looks like when rendered. It is not really a map right now but more of an outlining of the tiles I will render. The red coordinates are x and y values of the underlying source grid.
It is rendered with a zig-zag approach with an origin outside of the screen (top left). It is rendered row by row from left to right whereby every uneven row is inset by half a tiles width. This is a common approach to avoid having to fill the source 2D-grid with "zombie-data" if one would render it in a diamond approach.
What the algorithm does is:
- the screen is logically divided into square rectangles with a width of my tile width and height of my tile height, i.e. 128px by 64px
- the mouse coordinates are scaled by tile width and tile height and then floored. This determines in which screen rectangle the user clicked
- then the mouse coordinates are compared against the center coordinates of this rectangle
- regarding this result, a right angled triangle is calculated to check if the user clicked within a certain area of the rectangle. I am using the cosine of this triangle to compare against my initial rotation angle of 26,565 (atan of 0.5). This is the angle in which the sides of the rendered rhombi are rotated to achieve a 2:1 ratio of width and height (classic isometric projection for video games).
- regarding on where the user clicked
- the y value is determined from a lower and upper boundary
- the x value is determined based on y being even or uneven
Here is the algorithm (in c++):
//convert all input parameters to double
double mouseXPos = boost::numeric_cast<double>(pMouseXPos);
double mouseYPos = boost::numeric_cast<double>(pMouseYPos);
double tileWidth = boost::numeric_cast<double>(pTileWidth);
double tileHeight = boost::numeric_cast<double>(pTileHeight);
double tileWidthHalf = tileWidth / 2;
double tileHeightHalf = tileHeight / 2;
//calculate y position in screen grid
double mouseTileYPos = mouseYPos / tileHeight;
mouseTileYPos = std::floor(mouseTileYPos);
//calculate center pixel of the determined rectangle
int screenRectCenterX = ((std::floor((mouseXPos / tileWidth))) * tileWidth) + tileWidthHalf;
int screenRectCenterY = (mouseTileYPos * tileHeight) + tileHeightHalf;
//determine lower and upper boundary for y
int minY = boost::numeric_cast<int>(2 * mouseTileYPos);
int maxY = boost::numeric_cast<int>((2 * mouseTileYPos) + 1);
if (mouseYPos >= screenRectCenterY)
{
minY = maxY;
maxY++;
}
//calc triangle sides in pixels
char mouseRectangleSector[2]{};
double opposite;
double adjacent;
if (mouseYPos >= screenRectCenterY)
{
mouseRectangleSector[0] = 'S';
opposite = mouseYPos - screenRectCenterY;
}
else
{
mouseRectangleSector[0] = 'N';
opposite = screenRectCenterY - mouseYPos;
}
if (mouseXPos >= screenRectCenterX)
{
mouseRectangleSector[1] = 'E';
adjacent = (screenRectCenterX + tileWidthHalf) - mouseXPos;
}
else{
mouseRectangleSector[1] = 'W';
adjacent = tileWidthHalf - (screenRectCenterX - mouseXPos);
}
double hypothenuse = std::sqrt(std::pow(opposite, 2) + std::pow(adjacent, 2));
//calculate cos and corresponding angle in rad and deg
double cos = adjacent / hypothenuse;
double angleRad = std::acos(cos);
double angleDeg = angleRad * 180 / PI;
//calculate initial rotation angle in rad and deg
double controlAtan = 0.5;
double controlAngleRad = std::atan(controlAtan);
double controlAngleDeg = controlAngleRad * 180 / PI;
//determine final position for y
if (mouseRectangleSector[0] == 'S')
{
if (angleRad > controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
else
{
if (angleRad < controlAngleRad)
{
mouseTileYPos = maxY;
}
else
{
mouseTileYPos = minY;
}
}
//determine position for x
double mouseTileXPos;
if ((boost::numeric_cast<int>(mouseTileYPos)) % 2 == 0)
{
mouseTileXPos = (mouseXPos + tileWidthHalf) / tileWidth;
}
else
{
mouseTileXPos = mouseXPos / tileWidth;
}
mouseTileXPos = std::floor(mouseTileXPos);
std::cout << "grid coordinates x,y: " << mouseTileXPos << ","
<< mouseTileYPos << std::endl;
As I said, the algorithm works so i don't need help getting it to run. I am looking for help or advice on how to make it more compact (reduce lines of code). Maybe I can get rid of a couple of if statements by doing some more maths. This is really the first time after my graduation I used this kind of maths in programming so there might be some tweaks that can be done.
If there is no one who has an improvement for this, it can also serve as a solution or inspiration for other people.
c++ game
c++ game
New contributor
New contributor
New contributor
asked 7 mins ago
Tremah
1
1
New contributor
New contributor
add a comment |
add a comment |
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Tremah is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210695%2fmouse-coordinates-to-grid-coordinates-within-an-isometric-map%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Tremah is a new contributor. Be nice, and check out our Code of Conduct.
Tremah is a new contributor. Be nice, and check out our Code of Conduct.
Tremah is a new contributor. Be nice, and check out our Code of Conduct.
Tremah is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210695%2fmouse-coordinates-to-grid-coordinates-within-an-isometric-map%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown