Trazado de extensión de mosaico en una cuadrícula


8

Actualmente estoy trabajando en la búsqueda de ruta A * en una cuadrícula y estoy buscando suavizar la ruta generada, al mismo tiempo que considero la extensión del personaje que se mueve a lo largo de ella. Estoy usando una cuadrícula para la búsqueda de ruta, sin embargo, el movimiento del personaje es itinerancia libre, no es estricto movimiento de mosaico a mosaico.

Para lograr un camino más suave y más eficiente, estoy haciendo trazos de línea en una cuadrícula para determinar si hay mosaicos no transitables entre los mosaicos para eliminar las esquinas innecesarias.

Sin embargo, debido a que un trazo de línea es de extensión cero, no tiene en cuenta la extensión del personaje y da malos resultados (no devuelve fichas no caminables que la línea acaba de perder, causando colisiones no deseadas).

Entonces, lo que estoy buscando es en lugar de un algoritmo de línea que determine los mosaicos debajo de él, estoy buscando uno que determine los mosaicos debajo de una línea de extensión de todo el mosaico. ¡Aquí hay una imagen para ayudar a visualizar mi problema!

Aquí hay una imagen para ayudar a visualizar mi problema.

¿Alguien tiene alguna idea? He estado trabajando con la línea de Bresenham y otras alternativas, pero aún no he descubierto cómo resolver este problema específico.


Usaría dos líneas de Besenham con un ancho de media teja.
Jonathan Connell

Respuestas:


1

¿Qué tal si dibuja una línea desde cada esquina del 'mosaico' en el que se encuentra en cada esquina del mosaico al que desea ir? Probablemente incluso pueda optimizar esto a 3 líneas en lugar de cuatro. ¿No detectaría esto correctamente todos los mosaicos en el camino?

En cuanto a las rutas más suaves, consulte los artículos sobre "comportamiento de dirección", especialmente aquellos que lo combinan con A *, por ejemplo, estos enlaces:


0

¡Acabo de implementar este algoritmo para un juego mío hace un par de días! (-8

Aquí está mi idea en forma de imagen:

ingrese la descripción de la imagen aquí

Tenga en cuenta que el algoritmo funciona con rectángulos de cualquier tamaño. se basa en el hecho de que una esquina del rectángulo siempre colisiona primero con cualquier línea de cuadrícula. Esto significa que solo puede trazar un rayo y obtener todas las intersecciones que necesita.

Aquí está el algoritmo paso a paso:

  1. Elija la esquina "hacia adelante" de su rectángulo. Por ejemplo, en la imagen, la dirección de trazado se encuentra en el cuadrante superior derecho, por lo que elegimos la esquina superior derecha.
  2. Traza el rayo (ancho cero) desde esta esquina hasta tu destino. Debería iterar sobre todas las intersecciones de su rayo con líneas de cuadrícula.
  3. Para todas las intersecciones del rayo con líneas de cuadrícula, coloque su rectángulo en el punto de intersección. Su lado estaría exactamente a lo largo de una línea de cuadrícula, tocando varias celdas de la cuadrícula. ¡Estas son las fichas con las que tu rectángulo choca en este momento!

Aquí hay algunos casos extremos, como cuando el rayo es exactamente vertical / horizontal, o cuando golpea una esquina exactamente, pero no son difíciles.


0

Este procedimiento es una adaptación de bresenham, que resuelve la pregunta original.

trazar una línea del tamaño de un mosaico sobre una cuadrícula

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;
      }
    }
  }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.