This function represents a refusal to use any sort of trig to project the screen coordinates to tile coordinates. I am aware there are various ways to do this, but I was stubborn and was determined to figure it out on my own. The point is not to be the most efficient or legible, but to portray a level of problem solving ability.
point CMap::GetMouseTile(point& mouse)
{
// make sure we account for any map offset right away:
mouse.Offset(-m_nOSx, -m_nOSy);
point ptCurrMouseTileID;
const int halfWidth = (g_TileWidth >> 1);
const int halfHeight = (g_TileHeight >> 1);
// first find which rectangle the point's in:
int rectIDx, rectIDy;
ptCurrMouseTileID.x = rectIDx = mouse.x / g_TileWidth;
ptCurrMouseTileID.y = rectIDy = mouse.y / g_TileHeight;
if (ptCurrMouseTileID.y > 0) // does not apply to the first row
ptCurrMouseTileID.y = (ptCurrMouseTileID.y << 1);
// now find which quadrant it's in based upon the point's relative position in this rect
int adjX, adjY;
adjX = mouse.x - (rectIDx * g_TileWidth);
adjY = mouse.y - (rectIDy * g_TileHeight);
int quadrant = TOP_LEFT;
if (adjX >= halfWidth)
quadrant = TOP_RIGHT;
if (adjY >= halfHeight)
{
if (quadrant > 0)
quadrant = BTM_RIGHT;
else
quadrant = BTM_LEFT;
}
// now determine if the point is inside or outside the actual tile based upon which quadrant it's in
int result = -1;
switch (quadrant)
{
case BTM_RIGHT:
// for bottoms, if result > 0, the point is outside the tile
{
float d = (float)(halfHeight - g_TileHeight) / (float)(g_TileWidth - halfWidth);
result = adjY - g_TileHeight - (int)(d * (float)(adjX - halfWidth));
if (result > 0)
++ptCurrMouseTileID.y;
}break;
case BTM_LEFT:
{
float d = (float)(halfHeight - g_TileHeight) / (float)(-halfWidth);
result = adjY - g_TileHeight - (int)(d * (float)(adjX - halfWidth));
if (result > 0)
{ --ptCurrMouseTileID.x; ++ptCurrMouseTileID.y; }
}break;
case TOP_RIGHT: // for tops, if result is < 0, the point is outside the tile
{
float d = (float)halfHeight / (float)(g_TileWidth - halfWidth);
result = adjY - (int)(d * (float)(adjX - halfWidth));
if (result < 0)
--ptCurrMouseTileID.y;
}break;
case TOP_LEFT:
{
float d = (float)halfHeight / (float)(-halfWidth);
result = adjY - (int)(d * (float)(adjX - halfWidth));
if (result < 0)
{ --ptCurrMouseTileID.x; --ptCurrMouseTileID.y; }
}break;
}
// clamps:
if (ptCurrMouseTileID.x < 0)
ptCurrMouseTileID.x = 0;
if (ptCurrMouseTileID.y < 0)
ptCurrMouseTileID.y = 0;
if (ptCurrMouseTileID.x > m_nNumCols - 1)
ptCurrMouseTileID.x = m_nNumCols - 1;
if (ptCurrMouseTileID.y > m_nNumCols - 1)
ptCurrMouseTileID.y = m_nNumCols - 1;
// final result:
return ptCurrMouseTileID;
}