Innanzitutto, ecco il codice. Seguirà una spiegazione:
/*
* 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
};
}
};
Nota che questo codice non funzionerà per la mappa mostrata nella tua domanda. Questo perché le tessere dispari sono spostate a sinistra, mentre la tessera dispari è più spesso spostata a destra (come nel caso dell'editor di mappe piastrellate ). Dovresti essere in grado di rimediare facilmente modificando il valore x restituito nel caso dispari-tile.
Spiegazione
Questo può sembrare un metodo leggermente più bruto per eseguire questo compito, ma almeno ha il vantaggio di essere pixel perfetto e leggermente più flessibile.
Il trucco sta nel visualizzare la mappa non come un'unica griglia sfalsata, ma come due griglie sovrapposte l'una sull'altra. C'è la griglia delle righe dispari e la griglia delle righe pari, ma chiamiamole invece rosse e verdi in modo da poter creare un bel diagramma ...
Nota a destra di quell'immagine che ho segnato un punto con un punto viola. Questo è il punto di esempio che cercheremo di trovare nel nostro spazio delle piastrelle originale.
La cosa da notare su qualsiasi punto del mondo è che si troverà sempre esattamente in due regioni: una rossa e una verde (a meno che non sia su un bordo, ma probabilmente taglierai comunque entro il bordo frastagliato). Troviamo quelle regioni ...
Ora seleziona quale delle due regioni è quella corretta. Ci sarà sempre esattamente una risposta.
Da qui potremmo fare un po 'di aritmetica più semplice e calcolare la distanza quadrata dal nostro punto di campionamento a ciascun punto centrale delle due regioni. Qualunque sia il più vicino sarà la nostra risposta.
C'è comunque un modo alternativo. Per ogni area di test, campioniamo una bitmap che corrisponde alla forma esatta delle nostre piastrelle. Lo campioniamo in un punto tradotto in coordinate locali per quella singola tessera. Per il nostro esempio sarebbe simile a questo:
Uno a sinistra controlliamo la regione verde e otteniamo un colpo (pixel nero). Sulla destra testiamo la regione rossa e ci perdiamo (pixel bianco). Il secondo test è ovviamente ridondante poiché sarà sempre esattamente l'uno o l'altro, mai entrambi.
Arriviamo quindi alla conclusione che abbiamo un colpo nella tessera dispari a 1,1. Questa coordinata dovrebbe essere semplice da mappare alle coordinate del riquadro originale usando una trasformazione diversa per le righe pari e dispari.
Questo metodo consente anche di avere semplici proprietà per pixel sulle bitmap di test dei pixel. Ad esempio, il bianco è sfocato, il nero è un successo, il blu è acqua, il rosso è solido.