Traccia di estensione a livello di piastrella su una griglia


8

Attualmente sto lavorando su un * pathfinding su una griglia e sto cercando di smussare il percorso generato, considerando anche l'estensione del personaggio che si muove lungo di esso. Sto usando una griglia per l'individuazione del percorso, tuttavia il movimento del personaggio è un roaming libero, non un rigoroso movimento da piastrella a piastrella.

Per ottenere un percorso più fluido ed efficiente, sto facendo delle tracce su una griglia per determinare se ci sono tessere non percorribili tra le tessere per radere gli angoli non necessari.

Tuttavia, poiché una traccia di linea ha estensione zero, non tiene conto dell'estensione del personaggio e produce risultati negativi (non restituisce tessere non percorribili appena perse dalla linea, causando collisioni indesiderate).

Quindi quello che sto cercando è piuttosto che un algoritmo di linea che determina le tessere sottostanti, sto cercando uno che determina le tessere sotto una linea di estensione a tessera. Ecco un'immagine per aiutare a visualizzare il mio problema!

Ecco un'immagine per aiutare a visualizzare il mio problema

Qualcuno ha qualche idea? Ho lavorato con la linea di Bresenham e altre alternative, ma non ho ancora capito come risolvere questo problema specifico.


Vorrei usare due linee di Besenham alla larghezza di mezza tessera.
Jonathan Connell,

Risposte:


1

Che ne dite se tracciate una linea da ogni angolo della "tessera" in cui vi trovate ad ogni angolo della tessera in cui volete andare. Probabilmente puoi anche ottimizzarlo su 3 righe anziché su quattro. Questo non rileverà correttamente tutte le tessere sul percorso?

Per quanto riguarda i percorsi più fluidi, consulta gli articoli sul "comportamento dello sterzo", in particolare quelli che lo combinano con A *, ad esempio questi link:


0

Ho appena implementato questo algoritmo per un mio gioco un paio di giorni fa! (-8

Ecco la mia idea in forma di immagine:

inserisci qui la descrizione dell'immagine

Si noti che l'algoritmo funziona con rettangoli di qualsiasi dimensione. si basa sul fatto che un angolo del rettangolo si scontra sempre per primo con qualsiasi linea della griglia. Ciò significa che è possibile tracciare solo un raggio e ottenere tutte le intersezioni necessarie.

Ecco l'algoritmo passo-passo:

  1. Scegli l'angolo "in avanti" del rettangolo. Ad esempio, nell'immagine la direzione di tracciamento si trova nel quadrante in alto a destra, quindi scegliamo l'angolo in alto a destra.
  2. Traccia il raggio (larghezza zero) da questo angolo alla tua destinazione. Dovresti iterare su tutte le intersezioni del tuo raggio con le linee della griglia.
  3. Per tutte le intersezioni del raggio con linee della griglia, posizionare il rettangolo nel punto di intersezione. Il suo lato giaceva esattamente lungo una linea della griglia, toccando un numero di celle della griglia. Queste sono le tessere con cui il tuo rettangolo si scontra a questo punto!

Ci sono alcuni casi limite qui, come quando il raggio è esattamente verticale / orizzontale o quando colpisce esattamente un angolo, ma non sono difficili.


0

Questa procedura è un adattamento di Bresenham, che risolve la questione originale.

tracciare una linea delle dimensioni di una piastrella su una griglia

final int cols = 64;
final int rows = 64;
color tiles = new color[cols*rows];

void squaretrace(int x1, int y1, int x2, int y2, color c) {
  if (x1==x2 && y1==y2) {
    tiles[x1+y1*cols] += c;
  } else {
    // make sure y1 is less or equal to y2
    if (y2 < y1) {
      int t = x1;
      x1 = x2;
      x2 = t;
      t = y1;
      y1 = y2;
      y2 = t;
    }
    // along y-axis
    if (x1==x2) {
      for(int y = y1; y <= y2; y++){
        tiles[x1 + y * cols] += c;
      }
    }
    // along x-axis
    else if (y1==y2) {
      int xLo, xHi;
      if(x1 < x2){
        xLo = x1;
        xHi = x2;
      }
      else{
        xLo = x2;
        xHi = x1;
      }
      for(int x = xLo; x <= xHi; x++){
        tiles[x + y1 * cols] += c;
      }
    }
    // northeast
    else if (x1 < x2) { 
      // NW and SE corner
      int dx = x2 - x1;
      int dy = y2 - y1;
      int m = 8;
      int k = (1<<m) * dx / dy;

      int minx = x1 << m;
      int maxx = (x1+1) << m;

      for (int y = y1; y <= y2; y++) {
        int xLo = minx >> m;
        if (y!=y1) minx += k;
        if (y<y2) maxx += k;
        int xHi = (maxx-1) >> m;
        for (int x = xLo; x <= xHi; x++) {
          tiles[x+y*cols] += c;
        }
        tiles[xLo+y*cols] += c;
        tiles[xHi+y*cols] += c;
      }
    }
    // northwest
    else {
      // NW and SE corner
      int dx = x2 - x1;
      int dy = y2 - y1;
      int m = 8;
      int k = (1<<m) * dx / dy;

      int minx = x1 << m;
      int maxx = (x1+1) << m;

      for (int y = y1; y <= y2; y++) {

        if (y<y2) minx += k;
        int xLo = minx >> m;
        int xHi = (maxx-1) >> m;
        if (y!=y1) maxx += k;

        for (int x = xLo; x <= xHi; x++) {
          tiles[x+y*cols] += c;
        }
        tiles[xLo+y*cols] += c;
        tiles[xHi+y*cols] += c;
      }
    }
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.