Pixel de colisión

Started by Arcontus, October 18, 2010, 07:06:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Arcontus

Me alegro de como mínimo haber sacado un buen tema de discusión y de discurrir.

Se me había ocurrido lo que comenta SplinterGU, es decir, introducir por ejemplo 6 puntos en mi nave repartidos en el area de esta (dentro del grafico visible) y de alguna manera, revisar si son esos los puntos de colision, pero que yo sepa, collision no sirve para un punto de imagen ¿cierto?.

Respecto a rehacer toda la funcion collision para esto, no es la idea por rendimiento como también habéis comentado. Yo más bien estaba pensando que collision apuntara el primer pixel que colisiona en una variable de coordenadas para que posteriormente se pudiera consultar, algo similar a KEY y ASCII. No sería 100% preciso, pero para el efecto de chispas serviría.

Y como minimo le veo 2 utilidades:
* Hacer las chispas, obviamente.
* Calcular la dirección del rebote. Es decir que la nave salga disparada en dirección opuesta a la pared del mapa, simplemente calculando el angulo entre el centro de la (o X e Y del proceso) nave y el pixel que ha colisionado.

Este último punto que comento, es algo que estoy intentando discurrir, como realizar un rebote. Si no se si la nave ha impactado contra el mapa de frente o rozando de lado, es dificil determinar la dirección hacia donde debe rebotar la nave... no se si me explico. El mapa es totalmente irregular, pero collision es booleano.

Alguna idea más?

Saludos!
5Leaps, el primer juego comercial desarrollado para BennuGD. http://www.5leaps.com

Noivern

¿Alguien leyó lo que escribí?
Encuentro que usando trigonometría es la manera más simple, incluso se me ocurrio otra forma aun más fácil. A partir del centro del prota creas los chispasos. Debes calcular el ángulo entre la nave y con lo que choca, un simple get_angle() si es un proceso, y luego a las chispas darle un xadvance() con el angulo obtenido y la cantidad de pixeles definida como el radio de "mostrar la colision" de la nave, todo esto antes del primer frame de las chispas.
Como resultado veras las chispas crearse en un area de la zona en que chocó la nave. Como dije no es pixel exacto pero con varios chispasos (generador de particulas) ni se va a notar.

SplinterGU

#17
por supuesto que te leimos, pero no creo que sea tan simple como eso, aunque quizas una solucion cutre sea poniendo la chispa en la coordenada resultante del medio del box area de colision de ambos procesos, esto es:

- generamos 2 regiones segun el tamaño de cada grafico que colisiono (tambien se puede usar esto como algoritmo de colison) con centro en la mitad del grafico
- hacemos un region_union, y obtenemos una nueva region, que es la region de colision
- el centro de esta nueva region es el centro de la colsion y ahi tenemos donde poner la chispa.

con esto no me refiero a usar las funciones de REGION incluidas en bennu, porque creo que no estan todas exportadas, asi que quizas lo mejor es hacerlo a mano, son pocos calculos.

EDIT: estoy pesando que asi son las nuevas funciones de colision circle y colision box, no son pixel perfect, pero si colisionan por regiones, unas circulares y otras cuadradas, y podria meter alguna funcion adicional y opcional con parametros punteros x e y, para retornar el centro de la colision solo para estos 2 tipos de colision, no lo haria en pixel perfect.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

y ¿que tal poner las chispas en el medio de la distancia del centro ente los dos sprites colisionados?
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Windgate

Kagondio, estoy por hacer la prueba con un par de sprites que se mueven y detectar exactamente los píxeles de colisión para sacar ahí unos cuantos procesos chispa.

De acuerdo, eso consume, ¿Pero para qué tenemos las CPU de hoy en día?

Anda que no consume polígonos el ZBrush cuando modelas "a pico y pala", pero para eso tenemos esas cucarachitas circuiteadas xD

PD: Ni 100 líneas de código tendría esa cosa...
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

Arcontus

Quote from: DCelso on October 19, 2010, 08:43:52 PM
y ¿que tal poner las chispas en el medio de la distancia del centro ente los dos sprites colisionados?


El mapa es demasiaaado grande e irregular como para tener en cuenta esa posibilidad.

Respecto al metodo que comenta SplinterGU, no lo entendi. :(

Windgate, pues me harías un favor, o como minimo explicarme como harías la funcion y la intento hacer yo.

Gracias,

Saludos!
5Leaps, el primer juego comercial desarrollado para BennuGD. http://www.5leaps.com

SplinterGU

#21
Quote from: DCelso on October 19, 2010, 08:43:52 PM
y ¿que tal poner las chispas en el medio de la distancia del centro ente los dos sprites colisionados?


pues no, eso sirve si los graficos que colisionan son del mismo tamaño.

Quote from: Windgate on October 19, 2010, 11:14:45 PM
Kagondio, estoy por hacer la prueba con un par de sprites que se mueven y detectar exactamente los píxeles de colisión para sacar ahí unos cuantos procesos chispa.

De acuerdo, eso consume, ¿Pero para qué tenemos las CPU de hoy en día?

Anda que no consume polígonos el ZBrush cuando modelas "a pico y pala", pero para eso tenemos esas cucarachitas circuiteadas xD

PD: Ni 100 líneas de código tendría esa cosa...

despues lo van a querer correr en una consolita portatil.... y ahi no hay tanta cpu...

como extraño la programacion de la vieja escuela... :(

Quote from: Arcontus on October 19, 2010, 11:28:19 PM
Quote from: DCelso on October 19, 2010, 08:43:52 PM
y ¿que tal poner las chispas en el medio de la distancia del centro ente los dos sprites colisionados?


El mapa es demasiaaado grande e irregular como para tener en cuenta esa posibilidad.

Respecto al metodo que comenta SplinterGU, no lo entendi. :(

Windgate, pues me harías un favor, o como minimo explicarme como harías la funcion y la intento hacer yo.

Gracias,

Saludos!

poder ver el codigo del collision y del calculate_box o algo asi, en la lib de render.

es demasiado simple, pensa en 2 pedazos de papel cuadrados (cada 1 representa un grafico) cuando colisionan, ambos se superponen, y esa superposicion forma un nuevo rectangulo (no nos preocupemos en esta instancia por las rotaciones y tamaño, si necesitamos poder ver el codigo de la librender para calcular los corners -esquinas- del grafico) y ese nuevo rectangulo es el que digo yo, el centro de eso es el "punto caliente" de la colision.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Drumpi

Quote from: Arcontus on October 19, 2010, 11:28:19 PM
Quote from: DCelso on October 19, 2010, 08:43:52 PM
y ¿que tal poner las chispas en el medio de la distancia del centro ente los dos sprites colisionados?


El mapa es demasiaaado grande e irregular como para tener en cuenta esa posibilidad.

En ocasiones me alegro de usar un motor de tiles basado en proceso por tile ;D
No, en serio, la primera idea de hacerlo fue simplificar las colisiones de un submarino con el escenario.

Luego determiné que era más rápido usar 4 puntos de control y map_get_pixel!=0 ^^U
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Windgate

Se me ocurre una solución eficiente:

Una vez detectada la colisión de la nave con ese mapa taaaan graaaande, se lanzan 8 sondas, una en cada dirección, que comprueban dónde hubo colisión con el mapa.

Aquellas que detecten colisión con el mapa sacan chispas en ese punto y ya.

Pero sigo insistiendo en que no debería consumir tanto la solución de detectar exactamente los píxeles que chocan.
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

dale wind, hace la prueba y mete una cantidad razonable de procesos... unos 100 o 200... estaria bueno probarlo.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Arcontus

#25
Karma Up para SplinterGU, Windgate, Drumpi y DCelso.

SplinterGU, ahora entiendo que quieres decir, pero sigo sin saber como programarlo...

Windgate, me encanta la solucion de las sondas, es excelente como mínimo para el rebote de la nave y para la precisión de las chispas es cuestión de lanzar mas de 8 sondas :D.

A ver si este fin de semana tengo tiempo en programar la idea de Windgate y os cuento.

Drumpi, aun no se si utilizar tiles o no, por que el mapa es cerrado, algo así como un circuito y no se si es más optimo hacerlo por tiles o mediante un solo mapa. En definitiva si lo hiciera por tiles sería el mismo mapa recortado a cuadriculas y nuevamente montado.

Respecto a rendimiento, pues mientras más tire mejor, pero no está pensado para resoluciones inferiores a 1024x768 por la cantidad de elementos que hay que controlar, así que consolas descartado.

Saludos!
5Leaps, el primer juego comercial desarrollado para BennuGD. http://www.5leaps.com

Windgate

Me imagino que consumirá lo suyo y con muchos procesos se notará, pero si sólo es para hacerlo entre la nave protagonista y otros procesos no se ejecutará tan a menudo, sólo cuando haya una colisión que suele ser cada varios FRAMES y casi siempre con un sólo proceso cada vez.

Si lo pruebas sube el ejemplo, me gustaría mucho verlo :D
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

Arcontus

Quote from: Windgate on October 20, 2010, 07:44:21 PM
Me imagino que consumirá lo suyo y con muchos procesos se notará, pero si sólo es para hacerlo entre la nave protagonista y otros procesos no se ejecutará tan a menudo, sólo cuando haya una colisión que suele ser cada varios FRAMES y casi siempre con un sólo proceso cada vez.

Si lo pruebas sube el ejemplo, me gustaría mucho verlo :D

Lo prometido es deuda; Aquí tienes la funcion programada:


FUNCTION AnguloColision(int x1,int y1);
PRIVATE
int izq, der, arr, aba, indice, coincidencias, precision, escala;
BEGIN
x = x1;
y = y1;
//variables que guardaran el numero de coincidencias por lado
izq = 0;
der = 0;
arr = 0;
aba = 0;
coincidencias = 0;
//Numero de pixeles a partir de la coordenada de la nave que serán evaluados por cada lado
precision = 6;
//Escala entre el mapa y su grafico de durezas
escala = 500;

//Calculamos los pixeles de dureza del lateral "izquierdo".
for (indice = 0; indice < precision; indice ++)
x = x + escala;
if ((map_get_pixel(durezaFPG, 1, X /escala, Y /escala)) != 0);
izq++;
else
x = x + (escala/2);
END
END
    //En caso de haber encontrado pixels de colision por la "izquierda", aumentamos "coincidencias"
if (izq != 0) coincidencias++;END
//Restablecemos las coordenadas para calcular el siguiente bucle
x = x1;

    //Calculamos los pixeles de dureza del lateral "derecho".
for (indice = 0; indice < precision; indice ++)
x = x - escala;
if (map_get_pixel(durezaFPG, 1, X /escala, Y /escala) != 0);
der++;
else
x = x - (escala/2);
END
END
//En caso de haber encontrado pixels de colision por la "derecha", aumentamos "coincidencias"
if (der != 0) coincidencias++;END
//Restablecemos las coordenadas para calcular el siguiente bucle
x = x1;

//Calculamos los pixeles de dureza del lateral "abajo".
for (indice = 0; indice < precision; indice ++)
        y = y + escala;
if (map_get_pixel(durezaFPG, 1, X /escala, Y /escala) != 0);
aba++;
else
y = y + (escala/2);
END
END
//En caso de haber encontrado pixels de colision por "abajo", aumentamos "coincidencias"
if (aba != 0) coincidencias++;END
//Restablecemos las coordenadas para calcular el siguiente bucle
y = y1;

    //Calculamos los pixeles de dureza del lateral "arriba".
for (indice = 0; indice < precision; indice ++)
y = y - escala;
if (map_get_pixel(durezaFPG, 1, X /escala, Y /escala) != 0);
arr++;
else
y = y - (escala/2);
END
END
//En caso de haber encontrado pixels de colision por "arriba", aumentamos "coincidencias"
if (arr != 0) coincidencias++;END

//No podemos decidir cual es el lateral de escape si las 4 coordenadas dieran alguna "coincidencia".
//En el caso de que suceda, evaluaremos como angulo de escape aquel que tenga menos "coincidencias".
while (coincidencias == 4)
arr--;
aba--;
izq--;
der--;
coincidencias = 0;
    if (arr != 0) coincidencias++;END
    if (aba != 0) coincidencias++;END
    if (izq != 0) coincidencias++;END
    if (der != 0) coincidencias++;END
END

//En el caso de que haya 0 coincidencias (o bien por que no se detecta colision con el mapa de durezas,
//o bien por que con la "precision" establecida todos los lados tienen la misma cantidad de coincidencias, retornamos -1
if (coincidencias == 0) return -1;END
//En el caso de que haya más de 1 "coincidencia", retornamos el valor de la primera coordenada "libre" de colision.
if (coincidencias > 1)
if (izq == 0) return 0;END
if (der == 0) return 180000;END
if (arr == 0) return 90000;END
if (aba == 0) return 270000;END
END
//En el caso de que haya solo 1 coincidencia, retornamos el angulo inverso donde esta se localizo.
if (coincidencias == 1)
        if (izq == 1) return 180000;END
if (der == 1) return 0;END
if (arr == 1) return 270000;END
if (aba == 1) return 90000;END
END
//Si hubiera algun error en el proceso, retornamos -1.
return -1;
END


Como se podrá observar, la funcion es muy rudimentaria y mejorable a nivel de optimización de código, pero quería mostrarla lo más simple posible para que se entienda como funciona. Concretamente solo evalua 4 puntos cardinales con respecto a las coordenadas pasadas. Retorna el "mejor" valor de escape de la colisión contra el mapa de durezas.

Para que funcione, hay que configurar la variable escala, a la escala del mapa de durezas que utiliceis. Por otro lado, se tiene que tener en cuenta que el único pixel que cuenta como no colisionable, es el 0. Y por último obviamente el mapa de durezas.

Mis impresiones son positivas, ya que hace lo que necesitaba, y no observo bajada de rendimiento en el juego. Supongo que el hecho de que solo evalue "resolucion" x 4 coordenadas hace que sean pocos pixeles a evaluar, de manera que va bien la cosa...

Si alguien quiere usar esa funcion en su código, sientase libre de hacerlo.

Espero que les agrade la solución,

Saludos!
5Leaps, el primer juego comercial desarrollado para BennuGD. http://www.5leaps.com