2010-09-13 20 views
5

Sto cercando di capire come ottenere il riquadro corretto "attivo" sotto il mouse quando ho le tessere "ramp" e +1 altezza (vedi immagine sotto).Isometric Screen to Map


Example Isometric Image

Quando il mio mondo è piatto, tutto funziona senza alcun problema. Una volta che aggiungo una tessera con un'altezza di dire +1, insieme a una rampa che ritorna a +0, la mia schermata -> mappa di routine sta ancora guardando come se tutto fosse "piatto".

Nell'immagine sopra, la "rampa" verde è la piastrella reale che voglio rendere e calcolare il mouse -> mappa, tuttavia la piastrella blu che vedi "sotto" è l'area che viene calcolata. Quindi se muovi il tuo mouse in una qualsiasi delle aree verde scuro, pensa che sei su un'altra tessera.

Qui è la mia mappa render (molto semplice)

canvas.width = canvas.width; // cheap clear in firefox 3.6, does not work in other browsers 
for(i=0;i<map_y;i++){ 
    for(j=0;j<map_x;j++){ 
     var xpos = (i-j)*tile_h + current_x; 
     var ypos = (i+j)*tile_h/2+ current_y; 

     context.beginPath(); 
     context.moveTo(xpos, ypos+(tile_h/2)); 
     context.lineTo(xpos+(tile_w/2), ypos); 
     context.lineTo(xpos+(tile_w), ypos+(tile_h/2)); 
     context.lineTo(xpos+(tile_w/2), ypos+(tile_h)); 
     context.fill(); 

    } 
}  

E qui è il mio mouse -> mappa di routine:

ymouse=((2*(ev.pageY-canvas.offsetTop-current_y)-ev.pageX+canvas.offsetLeft+current_x)/2); 
xmouse=(ev.pageX+ymouse-current_x-(tile_w/2)-canvas.offsetLeft); 
ymouse=Math.round(ymouse/tile_h); 
xmouse=Math.round(xmouse/(tile_w/2)); 

current_tile=[xmouse,ymouse]; 

ho la sensazione che dovrò ricominciare da capo e mettere in atto un sistema di mappe basato sul mondo piuttosto che un semplice schermo -> mappa di routine.

Grazie.

risposta

2

L'assunzione è corretta. Per "scegliere" contro la geometria del mondo, la tua routine deve essere consapevole del mondo (e non solo della configurazione delle tessere di livello base). Cioè, senza alcun concetto di altezza delle tessere vicino a quello attualmente selezionato (dal tuo attuale algoritmo), non c'è modo di determinare se una tessera vicina (o una ancora più lontana, a seconda dell'altezza consentita) dovrebbe essere intercettato da raccogliere raggio.

Hai già il punto finale del tuo raggio di raccolta. Ciò che rimane è definire il resto del raggio, nello spazio del mondo, e controllare quel raggio per le intersezioni con la geometria del mondo.

2

Se, come l'immagine, il tuo angolo di vista è sempre 45 gradi e sempre dalla stessa direzione, il mouse -> mappa di routine potrebbe utilizzare un qualcosa di algoritmo simile:

  1. calcolare i, j della piastrella come stai facendo attualmente (il tuo valore finale di xmouse, ymouse)
  2. Cerca altezza e angolo di piastrella a, j
  3. data l'altezza e l'angolo, questa tessera interseca il raggio di raccolta? Se è così, imposta lasti, lastj = i, j
  4. incremento/decremento i, j un passo in diagonale verso il visualizzatore
  5. siamo caduti dal bordo della mappa? Se è così, torna lasti, lastj. Altrimenti torna a 2.

A seconda dell'altezza massima di una tessera, potresti dover controllare solo 2 tessere, piuttosto che andare fino al bordo della mappa.

3 è la parte difficile e dipende dalla geometria del mondo. Disegna alcuni triangoli e dovresti riuscire a capirlo. Oppure potresti provare a guardare la funzione intersect_quadrilateral_ray() here.