Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





[XNA] Detección de colisión por píxel con posición relativa y textura rotada

Iniciado por NachoDA, 02 de Mayo de 2012, 04:13:32 PM

« anterior - próximo »

NachoDA

Hola! Quería pediros ayuda, a ver qué podéis decirme sobre el problema que tengo.

En el juego que estoy desarrollando uno de los enemigos digamos que tiene una forma compleja, por lo que me es necesario hacer una colisión que compruebe píxel a píxel si hay o no contacto. La colisión se tratada es Enemigo -> Disparo. El disparo es tan pequeño que no comprobaré todos los píxeles si hacen contacto; tan sólo evaluaré si en posDisparo hay un píxel "coloreado" (es decir, si en el canal Alpha es igual a 0) una vez hace contacto con la caja del Enemigo.

Así pues, tengo lo siguiente:


Para calcular los píxels de la textura, hago lo de siempre: guardo en un array unidimensional las posiciones de cada uno de ellos y sus datos (cada canal: A, R, G & B). De la siguiente forma, calcularía el píxel de la textura que debo comprobar en la colisión:


Pero aquí llega el problema. El hijo de puta Enemigo rota constantemente, por lo que daría una situación como la siguiente, la cuál no sé cómo resolver:


¿Alguna idea de cómo calcular ese punto de la MatrizPíxel? ¿Alguna otra solución? ¿Algo? Gracias.  >.<

Para los moderadores: No sabía muy bien si colocarlo aquí, en el Foro de XNA, o en el de General Programadores. Si me he equivocado de lugar, disculpadme ^^.
@NachoDA

"Actually DLC nowadays stands for Disc Locked Content" - Usuario descontento

blau

En general es mala idea lo del detección por pixels, con una lista de circulos o de cuadrados podrias alcanzar el mismo objetivo con mayor eficiencia, pero alla tu...  ^_^'


La transformacion que necesitas es


     Transform local =  Mtrix.CreateTranslation(-Origin) * Matrix.CreateRotationZ(angle)*Matrix.CreateTranslation(Position);

    De esta forma si trnasformas cualquier vector del espacio local del enemigo te devolvera un vector en las coordeanadas de mundo.

  Por ejemplo... que se que esto cuesta...

    Posicion enemiga = (100, 100)
    Origen = (25,25)  // Supongo que la textura es de 50,50 y quieres tenerla centrada respecto al angulo de rotacion

Si la  Rotacion = 0

   Si transformas la posicion (0,0) de tu textura, Vector2.Transform( (0,0) , local) te devolverá (75,75)

   Si transformas la posicion (50,50) de tu textura, Vector2.Transform( (50,50) , local) te devolverá (125,125)

Si la rotación fuese de 180º

   Si transformas la posicion (0,0) de tu textura, Vector2.Transform( (0,0) , local) te devolverá (125,125)

   Si transformas la posicion (50,50) de tu textura, Vector2.Transform( (50,50) , local) te devolverá (75,75)

Y con tu player igual, de esa forma tendrias todas las coordenadas en el mismo espacio.

Tambien en vez de en espacio mundo, puedes trabajar en el espacio de uno de los objetos... pero eso es mas dificil de pillar...


NachoDA

Gracias por la respuesta. Veamos, este es un esquema del enemigo.



He desechado la idea de los rectángulos (que es la que uso para el resto de las naves por lo siguiente: Para hacer la figura necesitaría 9 rectánglos. Además, tomando en cuenta que la figura rota, tengo que calcular los puntos de cada rectángulo en base al nuevo ángulo. Es por eso que he preferido hacerlo por píxeles.
@NachoDA

"Actually DLC nowadays stands for Disc Locked Content" - Usuario descontento

blau

Pues está tirado de calcular...

Si cogemos la transformacion del mensaje anterior y la invertimos... trabajaras en el espacio del objeto...

LocalInverted = Matrix.Invert(Local);

PosDisparoLocal = Vector3.Transform(PosDisparoWorld, LocalInverted);

Es decir, la posicion de la bala te vendra dada relativa a la esquina superior izquierda de tu enemigo... y trabajaras como si no estuviera rotado...

es decir... que calcular si hay choque lo puedes hacer muy facil.... si quieres usar rectangulos los usas, no tendras que rotarlos...

El rectangulo del centro,  si el tamaño total es 50x50 y del centro 20x20,  es (15,15,20,20) para todos los enemgios en cualquier posicion o rotacion....

Y si quieres hacerlo sin rectangulos puedes calcular directamente si la bala toca cualquier zona, al estar alineados los ejes es muy sencillo... pero yo no me complicaría...

;)

PD: Solo necesitas 7 rectángulos, no 9 ;)

NachoDA

Mira, siendo sincero no he entendido completamente el código, pero lo he implementado y, joder, funciona. Mañana lo miraré con más detenimiento a ver qué es exactamente lo que pasa.

Gracias, blau!
@NachoDA

"Actually DLC nowadays stands for Disc Locked Content" - Usuario descontento

blau

xD

Pues te juro que a mi me hubiese gustado que me lo explicaran así.... :)

noob

¿@blau podrías explicar con más detalle el funcionamiento de este método? No acabo de comprender algunos aspectos. Ésto me ayudará a aprender mejor el sistema :-[

Muchas gracias por adelantado :)

blau

Bueno, no se muy bien donde te has perdido...

pero básicamente se trata de hacer los cálculos desde un punto de referencia distinto.

En la primera imagen tu estas en el (0,0) mirando hacia el frente y ves dos rectángulos rotados, los cálculos para saber si colisionan son complicados.

En la segunda imagen estas en una esquina de uno de los cuadrados mirando hacia el frente, tu base o tu referencia ha cambiado, para ti ese rectángulo no está rotado, es un rectángulo alineado con los ejes, ahora el único que está rotado es el otro rectángulo que quedaba, pero los cálculos para ver si colisionan ahora son mucho más fáciles...


Así que eso es lo que se hace, trabajar en el espacio o base de uno de los rectángulos

Espero que te haya ayudado...

Un saludo

noob

Comprendo correctamente que se cambia el punto de referencia. Lo que no comprendo es la parte "matemática"(?) de trabajo con matrices...
Gracias por la explicación.

blau

Esta matriz lo que hace es convertirte coordenadas de espacio objeto a coordenadas de mundo

Transform local =  Mtrix.CreateTranslation(-Origin) * Matrix.CreateRotationZ(angle)*Matrix.CreateTranslation(Position);

La inversa hace lo contrario, te pasa coordenadas de mundo a coordenadas de objeto,  que es lo que necesitas para trabajar en espacio objeto..

el por qué y cómo funciona es cuestión tratada en libros de álgebra lineal.. ahora mismo no sé recomendarte ninguno... pero el concepto es "matriz de transformación de cambio de base"...
aunque esto es una herramienta... y no tienes porque saber como se hacen las herramientas, simplemente tienes que saber como usarlas...

Un saludo

jbosch

Jesús Bosch Aiguadé
PLUNGE INTERACTIVE
------------------
Twitter:
@plungeint
@jboschaiguade
------------------
Facebook:
http://www.facebook.com/plungeinteractive








Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.