Hier ist zunächst der Code. Eine Erklärung folgt:
/*
* tw, th contain the tile width and height.
*
* hitTest contains a single channel taken from a tile-shaped hit-test
* image. Data was extracted with getImageData()
*/
worldToTilePos = function(x, y) {
var eventilex = Math.floor(x%tw);
var eventiley = Math.floor(y%th);
if (hitTest[eventilex + eventiley * tw] !== 255) {
/* On even tile */
return {
x: Math.floor((x + tw) / tw) - 1,
y: 2 * (Math.floor((y + th) / th) - 1)
};
} else {
/* On odd tile */
return {
x: Math.floor((x + tw / 2) / tw) - 1,
y: 2 * (Math.floor((y + th / 2) / th)) - 1
};
}
};
Beachten Sie, dass dieser Code für die in Ihrer Frage gezeigte Karte nicht sofort funktioniert. Dies liegt daran, dass die ungeraden Kacheln nach links versetzt sind, während die ungeraden Kacheln normalerweise nach rechts versetzt sind (wie dies im gekachelten Karteneditor der Fall ist ). Sie sollten in der Lage sein, dies einfach zu beheben, indem Sie den im Fall der ungeraden Kacheln zurückgegebenen x-Wert anpassen.
Erläuterung
Dies scheint eine etwas brutalere Methode zur Erfüllung dieser Aufgabe zu sein, hat jedoch zumindest den Vorteil, dass sie pixelgenau und etwas flexibler ist.
Der Trick besteht darin, die Karte nicht als einzelnes versetztes Gitter anzuzeigen, sondern als zwei übereinanderliegende Gitter. Es gibt das Raster mit ungeraden Zeilen und das Raster mit geraden Zeilen, aber nennen wir sie stattdessen rot und grün, damit wir ein hübsches Diagramm erstellen können ...
Beachten Sie, dass ich rechts von diesem Bild einen Punkt mit einem violetten Punkt markiert habe. Dies ist der Beispielpunkt, den wir versuchen werden, in unserem ursprünglichen Kachelraum zu finden.
An jedem Punkt der Welt ist zu beachten, dass er immer in genau zwei Regionen liegt - einer roten und einer grünen (es sei denn, er befindet sich an einer Kante, aber Sie werden wahrscheinlich trotzdem innerhalb der gezackten Kantengrenze abschneiden). Lassen Sie uns diese Regionen finden ...
Wählen Sie nun aus, welche der beiden Regionen die richtige ist. Es wird immer genau eine Antwort geben.
Von hier aus könnten wir eine einfachere Arithmetik durchführen und den quadratischen Abstand von unserem Abtastpunkt zu jedem Mittelpunkt der beiden Regionen berechnen. Was am nächsten ist, wird unsere Antwort sein.
Es gibt jedoch einen alternativen Weg. Für jede Testregion probieren wir eine Bitmap aus, die der genauen Form unserer Kacheln entspricht. Wir probieren es an einem Punkt aus, der in lokale Koordinaten für diese einzelne Kachel übersetzt wurde. In unserem Beispiel würde es ungefähr so aussehen:
Links überprüfen wir den grünen Bereich und erhalten einen Treffer (schwarzes Pixel). Rechts testen wir den roten Bereich und erhalten einen Fehler (weißes Pixel). Der zweite Test ist natürlich überflüssig, da es immer genau der eine oder andere sein wird, niemals beide.
Wir kommen dann zu dem Schluss, dass wir bei 1,1 einen Treffer in der ungeraden Kachel haben. Diese Koordinate sollte einfach auf die ursprünglichen Kachelkoordinaten abzubilden sein, wobei eine andere Transformation für ungerade und gerade Zeilen verwendet wird.
Mit dieser Methode können Sie auch einfache Eigenschaften pro Pixel für die Pixeltest-Bitmap (s) festlegen. ZB Weiß ist Off-Tile, Schwarz ist ein Hit, Blau ist Wasser, Rot ist fest.