Ir al contenido

publicidad
publicidad

Foto

[Ayuda] deteccion de colisiones por píxeles


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
3 respuestas en este tema

  • uziel5

  • Valefor

  • vida restante: 100%
  • Registrado: 08 sep 2007
  • Mensajes: 1.955
#1

Escrito 19 abril 2011 - 23:54

Hola, verán estoy estudiando ahora mismo programación de videojuegos en 2D, el lenguaje de programación que estoy usando en C# en XNA, ahorita estoy en el tema de detección de colisiones por píxeles y lo que pasa es que no acabo de entender todo el código, que es el siguiente:

[code:1]public static bool evaluarPixeles(Rectangle rectanguloA, Color[] datosA,
Rectangle rectanguloB, Color[] datosB)
{

//Obtengo el área que está colisionando

int arriba = Math.Max(rectanguloA.Top, rectanguloB.Top);
int abajo = Math.Min(rectanguloA.Bottom, rectanguloB.Bottom);
int izquierda = Math.Max(rectanguloA.Left, rectanguloB.Left);
int derecha = Math.Min(rectanguloA.Right, rectanguloB.Right);

//Recorro píxel por píxel del area en colision

for (int y = arriba; y < abajo; y++)
{
for (int x = izquierda; x < derecha; x++)
{
Color colorA = datosA[(x - rectanguloA.Left) + (y - rectanguloA.Top) * rectanguloA.Width];
Color colorB = datosB[(x - rectanguloB.Left) + (y - rectanguloB.Top) * rectanguloB.Width];

//si los píxeles obtenidos no son transparentes hay colision

if (colorA.A != 0 && colorB.A != 0)
{
return true;
}
}
}
return false;
}[/code]

Lo que no entiendo es lo siguiente:

[code:1]for (int y = arriba; y < abajo; y++)
{
for (int x = izquierda; x < derecha; x++)
{
Color colorA = datosA[(x - rectanguloA.Left) + (y - rectanguloA.Top) * rectanguloA.Width];
Color colorB = datosB[(x - rectanguloB.Left) + (y - rectanguloB.Top) * rectanguloB.Width];

if (colorA.A != 0 && colorB.A != 0)
{
return true;
}[/code]

Se que voy recorriendo pixel a pixel pero no entiendo como va obteniendo estos, el código es 100% funcional, pero no me gusta programar cosas que no acabo de entender, si me pueden ayudar se los agradecería mucho.

Otra cosa que me gustaría ver, es que supongamos que tengo todo un mapa y varios obstáculos en el, y dentro tengo un personaje el cual es controlable, ¿para saber si hay colisiones tengo que comprobar cosa por cosa?, por que en juegos grandes hay una cantidad considerable de objetos con los que puede colisionar un personaje, eso sin contar a los enemigos y creo que sería algo muy laborioso para la máquina.

saludos

  • Caid

  • Ultima

  • vida restante: 100%
  • Registrado: 07 ene 2003
  • Mensajes: 1.810
#2

Escrito 20 abril 2011 - 11:45

Hola.

Bueno, por lo que veo los "sprites" están almacenados en los arrays unidimensionales datosA y datosB. Para recorrerlo se usa la fórmula

(x - rectanguloA.Left) + (y - rectanguloA.Top) * rectanguloA.Width

(x - rectanguloA.Left) devuelve la posición relativa de x en el array. Es decir, x respecto al inicio del array.

Después se le suma la posición de y multiplicada por el ancho del array. Ésto se hace para traducir un par de coordenadas (x,y) en una única coordenada unidimensional. datosA[x+y*ancho] equivale a datos[x,y] No sé porqué han usado una única coordenada para el array.

En cuanto a tu última duda; sí, tienes razón, mirar pixel a pixel es un proceso muy laborioso. Por eso se suelen usar métodos más eficientes. En general, se le asigna un objeto geométrico (p.ej. un círculo, un cuadrado o un cubo en 3d) a cada objeto que colisiona, y se comprueba si las geometrías están en contacto. Es menos exacto, pero infinitamente más rápido. Te dejo un enlace explicativo:

http://juank.black-b...-colisiones-2d/

Saludos.

  • Ollydbg

  • Valefor

  • vida restante: 100%
  • Registrado: 05 sep 2008
  • Mensajes: 6.259
#3

Escrito 20 abril 2011 - 20:58

uziel5 aquí tienes una explicación "para torpes" de pixel perfect collision para XNA


Imagen Enviada


Imagen Enviada

.NET Tutorial 34. XNA y pixel perfect collision

Fijate que ahí solo se evalúa la colisión cuando existe una intersección de las regiones implicadas, ya que es una "tontería" estar evaluando la colisión si ni siquiera las dos regiones (los dos cuadrados que delimitan el ancho y alto de los sprites) se estan interseccionando :)
Y además, para optimizar un poco más el código, la intersección que se evalúa es la región resultante de la intersección (lo que representa o intenta representar el recuadro "amarillo" de las imagenes anteriores).
De esta forma, nos dá un poco "igual" si los sprites son de 2000x2000 pixels, ya que si el área a evaluar es de apenas 25x25 pixels la detección es prácticamente instantanea.
(amén de que también se sale del bucle de comprobación en el primer pixel que se encuentra que esta colisionando, con lo cual el proceso es más rápido si cabe)

Usando esa técnica tienes la ventaja de la rápidez de las colisiones por regiones (bounding box) pero además la precisión de la colisión a nivel de pixel (cosa que no obtienes si solo haces colisiones por regiones)

Saludos.

  • uziel5

  • Valefor

  • vida restante: 100%
  • Registrado: 08 sep 2007
  • Mensajes: 1.955
#4

Escrito 20 abril 2011 - 21:45


Muchísimas gracias por la ayuda, con tu explicación he acabado de entenderlo, antes había tomado una hoja y papel con cuadros imaginarios para ver como fusionaba esto pero estaba haciendo unas cosas mal, pero ya que me lo has explicado un poco lo he logrado entender, con respecto a la pregunta que hice, antes de analizar si se presenta una colisión por píxeles, verifico si hay colisión de rectángulos, para no estar haciendo cálculos innecesarios ^^.


La mismas técnicas de las que me hablas las estoy utilizando en mis juegos, como dices, primero compruebo si hay colisión de rectángulos, de ser el caso, compruebo si hay colisión de píxeles solo del área que está colisionando, el tutorial que me pones, ¿es de uno de los blogs gamefilia verdad?, les he echado un ojo y me han venido bien mas de una vez.

Y vuelvo de nuevo a la pregunta que hice antes, ¿entonces hay que preguntar si el personaje colisiona con cada uno de los bounding box para verificar si hay colisión?, igual se me hace algo un poco laborioso jeje, quizás sea por que soy muy nuevo en esto de la programación orientada a objetos y la programación de videojuegos.

Muchas gracias a los dos por la ayuda que me han dado hasta ahora, me ha venido bastante bien.

un saludo.


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
publicidad
publicidad