NEW AND IMPROVED! OLD AND TERRIBLE D:
// returns the tile list under the given x, y coordinates. struct list ** mapCoordUnderLocation (struct map *m, float x, float y) { float xRem = fmod (x, 45.0), xRemAbs = fabs (xRem), x1 = x - xRem, x2 = x + (x < 0 ? -(45.0 - xRemAbs) : 45.0 - xRemAbs), yRem = fmod (y, 26.0), yRemAbs = fabs (yRem), y1 = y - yRem, y2 = y + (y < 0 ? -(26.0 - yRemAbs) : 26.0 - yRemAbs), swap = 0, mag1 = 0, mag2 = 0; int xFinal, yFinal; if (fabs (fmod (x1, 90)) < FLT_EPSILON || fabs (x1) < FLT_EPSILON) { swap = x1; x1 = x2; x2 = swap; } if (fabs (fmod (y1, 52)) < FLT_EPSILON || fabs (y1) < FLT_EPSILON) { swap = y1; y1 = y2; y2 = swap; } mag1 = sqrt((x-x1) * (x-x1) + (y-y1) * (y-y1)); mag2 = sqrt((x-x2) * (x-x2) + (y-y2) * (y-y2)); if (mag1 < mag2) { xFinal = (int)(x1 / 45.0); yFinal = (int)((y1 - xFinal * 26.0) / 52.0); } else { xFinal = (int)(x2 / 45.0); yFinal = (int)((y2 - xFinal * 26.0) / 52.0); } return mapLocation (m, xFinal, yFinal); } // this is a mess. There has got to be some way to write this more compactly. void calcCursorTile(float locX, float locY, int *fx, int *fy) { double fractionalX, fractionalY; double interpolationX, interpolationY; double selectedX, selectedY; unsigned char flip; fractionalX = fmod(locX, 9.0); if(fabs(fractionalX) > 3.0 && fabs(fractionalX) < 6.0) { // complexities! Depending on Y height & column offset, cursor could be over either column if(fmod(fractionalX < 0 ? locX - (9.0 + fractionalX) : locX - fractionalX, 18.0) == 0) { // lower column is multiple of 18 & uses flat tiles fractionalY = fmod(locY, 10.4); } else { // lower column is multiple of 9 & uses offset tiles fractionalY = fmod(locY, 10.4); flip = 1; } if((!flip && ((fractionalY > -5.2 && fractionalY < 0.0) || (fractionalY > 5.2 && fractionalY < 10.4))) ||
(flip && !((fractionalY > -5.2 && fractionalY < 0.0) || (fractionalY > 5.2 && fractionalY < 10.4)))) { // this covers all the hex slopes like this: / if(fractionalY < -5.2) { // somewhere between -10.4 and -5.2 interpolationY = (fractionalY + 10.4) / 5.2; // now between 0 and 1 } else if(fractionalY < 0.0) { // somewhere between -5.2 and 0.0 interpolationY = (fractionalY + 5.2) / 5.2; } else if(fractionalY < 5.2) { // somewhere between 0.0 and 5.2 interpolationY = fractionalY / 5.2; } else { // somewhere between 5.2 and 10.4 interpolationY = (fractionalY - 5.2) / 5.2; } if(fractionalX < 0) { interpolationX = (fractionalX+6.0)/3.0; } else { interpolationX = (fractionalX-3.0)/3.0; } // greater than zero rounds left (down), less than rounds right (up) // printf("y: base- %f norm- %f; x: base- %f norm- %f; %f\n", fractionalY, \ selectedTileY, fractionalX, selectedTileX, selectedTileY - selectedTileX); if(interpolationY - interpolationX > 0.0) { selectedX = fractionalX < 0 ? locX - (9.0 + fractionalX) : locX - fractionalX; if(flip) { selectedY = fractionalY < 0 ? locY - fractionalY - 5.2 : locY + (5.2 - fractionalY); } else { selectedY = fractionalY < 0 ? locY - fractionalY : locY + (10.4 - fractionalY); } } else { selectedX = fractionalX < 0 ? locX - fractionalX : locX + (9.0 - fractionalX); if(flip) { selectedY = fractionalY < 0 ? locY - (10.4 + fractionalY) : locY - fractionalY; } else { selectedY = fractionalY < 0 ? locY - (5.2 + fractionalY) : locY - fractionalY + 5.2; } } } else { // this covers all the hex slopes like this: \ .. if(fractionalY < -5.2) { // somewhere between -10.4 and -5.2 interpolationY = (fractionalY + 10.4) / 5.2; // now between 0 and 1 } else if(fractionalY < 0.0) { // somewhere between -5.2 and 0.0 interpolationY = (fractionalY + 5.2) / 5.2; } else if(fractionalY < 5.2) { // somewhere between 0.0 and 5.2 interpolationY = fractionalY / 5.2; } else { // somewhere between 5.2 and 10.4 interpolationY = (fractionalY - 5.2) / 5.2; } if(fractionalX < 0) { interpolationX = (fractionalX+6.0)/3.0; } else { interpolationX = (fractionalX-3.0)/3.0; } if(interpolationY + interpolationX < 1.0) { selectedX = fractionalX < 0 ? locX - (9.0 + fractionalX) : locX - fractionalX; if(flip) { selectedY = fractionalY < 0 ? locY - fractionalY - 5.2 : locY + (5.2 - fractionalY); } else { selectedY = fractionalY < 0 ? locY - (10.4 + fractionalY) : locY - fractionalY; } } else { selectedX = fractionalX < 0 ? locX - fractionalX : locX + (9.0 - fractionalX); if(flip) { selectedY = fractionalY < 0 ? locY - fractionalY : locY + (10.4 - fractionalY); } else { selectedY = fractionalY < 0 ? locY - (5.2 + fractionalY) : locY - fractionalY + 5.2; } } } } else { if(fabs(fractionalX) <= 3.0) { // cursor is safely in round-down (towards zero) hex column selectedX = locX - fractionalX; } else if(fabs(fractionalX) >= 6.0) { // cursor is safely in round-up (away from zero) hex column selectedX = fractionalX < 0 ? locX - (9.0 + fractionalX) : locX + (9.0 - fractionalX) ; } if(fmod(selectedX, 18.0) == 0) { fractionalY = fmod(locY, 10.4); } else { fractionalY = fmod(locY-5.2, 10.4); } if(fabs(fractionalY) < 5.2) { selectedY = locY - fractionalY; // round down Y } else { selectedY = fractionalY < 0 ? locY - (10.4 + fractionalY) : locY + (10.4 - fractionalY); } } selectedX = selectedX / 9.0; selectedY = ((selectedY-(5.2*selectedX)) / 10.4); // there is a minute amount of floating point error in the above calcuation
that lead to the cursor appearing over the wrong tile on occasion. selectedY += (selectedY < 0 ? -0.0001 : 0.0001); if(fx != NULL && fy != NULL) { *fx = (int)selectedX; *fy = (int)selectedY; } }