Capa de abstracción para Chipmunk.

Started by Erkosone, January 16, 2013, 04:56:10 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Erkosone

Buenas tardes comunidad, llevaba mucho tiempo creando mi propia librería de física para vídeo juegos, y recientemente he probado la estupenda Chipmunk portada a bennuGD..
Me he quedado maravillando con lo bien que funciona :)


Y como todos o casi todos los que andamos por aquí venimos del amor por Div y Div2, pues me he dicho..  por que no crear una colección de funciones que ayuden hasta el infinito a simplificar el uso de la chipmunk en bennuGD?


Pues eso, que comienzo lo que espero que sea una ayuda para todo el que quiera disponer de una serie de funciones "al mas puro estilo DIV" para trabajar con física en bennuGD haciendo juegos.


Los objetivos que tengo marcados como iniciales son estos:
- Crear un editor gráfico para el diseño de los escenarios.
- Crear las funciones que cargan el escenario "scroll" o mode7 completamente vectorizado.
- Crear un API "DIV-Style" para el uso de la chipmunk en bennuGD.


EL EDITOR:
Como avance, el editor gráfico de escenarios lo comencé a crear por allá en el 2009, y durante estos años lo he ido puliendo hasta dejarlo perfectamente operativo.
Creo que será una gran ayuda para los que nos dedicamos a crear juegos, lo que permite es navegar por un gráfico cargado desde disco y mediante unas simples herramientas miy similares a las del editor de mapas de Div2 pero llevadas a la actualidad poder setear puntos de control en un mapa, tiene zoom y mas cosillas interesantes.


En realidad no solo es un editor de puntos de control, también trae una herramienta que permite cargar un tileset desde un simple PNG/BMP/JPG y recortar sprites como lo hacía el editor de Div2, y bueno, bastantes cosillas mas ;)


El editor es Open Source, abierto a cualquier tipo de cambio, modificación o lo que haga falta.


LAS FUNCIONES DE CARGA DE ESCENARIOS:
- Serán simples funciones cuyo principal objetivo es el de teclear algo como esto: INT chipmunk_load_scenario( string cpt_file );  y chipmunk_make_scenario( int id_scenario );
Como se ve, es lo mas simple del mundo XD.. la idea es que respete al máximo la filosofía DIVERA.


LA CAPA DE ABSTRACCION PARA CHIPMUNK EN BENNUGD:
- Esta es la parte que mas trabajo tiene, se trata de una gran colección de funciones que permiten realizar cualquier tipo de acción sobre los objetos, por poner algunos ejemplos:
- INT chipmunk_build_entity(  float raduis, float mass  );
- chipmunk_set_entity( int entity_id );
- chipmunk_add_velocity( int entity_id, float velocity, float angle );
- chipmunk_entiy_brake( int entity_id, int brake_percent );




Llevo mucho tiempo con este tema, no es una idea que se me acaba de ocurrir XD.. el proyecto está ya maduro y es funcional, pero no está terminado, en cuanto lo tenga todo listo lo publicaré para uso y disfrute de todos, siendo posible crear un juego con física en scroll o mode7 con tan solo 20 lineas de código o menos ;)
Por la dificultad de como usarlo que no se preocupe nadie.. voy a montar unos vídeo tutoriales como los que vengo haciendo desde hace ya años para otros menesteres, ahora dedicados a bennuGD y al uso de chipmunk con el.




La idea principal de todo esto es la de eliminar o "en la medida de lo posible" evitar montar complicados códigos que comprueban coordenadas en un mapa de durezas, automatizando todo esto mediante un escenario vectorizado.


Bueno.. espero tener pronto esto listo, sinceramente, me muero de ganas por publicarlo y ver que os parece, ya que espero que sea una grata alternativa que nos ahorre tiempo a todos a la hora de crear vídeo juegos ;)

alex

Guauuu, lo he leido y me he quedado flipando xd. Lo de las funciones que vienes haciendo, creo que que muy largas, al escribir, y memorizar. Lo de que ahorre escribir lineas a keoh le va q gustar el que mas xdd. Suena bien, ya pronto se programara una fisica como la de bad piggies, (( ese juego me dejo flipado con la fisica) o mejor. Surrte con el prroyecto.

Erkosone

Gracias ALEX, la idea es que podamos programar un juego de scroll o mode7 igual de fácil que como se hace en div, pero evitando todo ese royo de comprobar durezas.


Osea.. imaginate un proceso personaje como este:


process personaje(x,y);
begin
chipmunk_build_entity( 50, 10 );   50 de radio y 10 de masa..
chipmunk_entity_set_position( this, x, y );   coloco al personaje en las coordenadas pasadas como parámetros a este proceso..


ale.. ya está todo el control de colisiones creado XD..


ahora el loop para mover al perso..


LOOP en pseudo código:
if(tecla LEFT) chipmunk_entity_Add_velocity( this, 0.1, 180000 );end
if(tecla RIGHT) chipmunk_entity_add_velocity( this, 0.1, 0 );end




con eso ya te mueves para izquierda/derecha..


Para un salto usando una simple variable llamada 'ESTADO'


switch(estado)
si vale cero -> si pulso key UP -> estado vale 1..
si vale uno -> chipmunk_entity_add_velocity( this, 4.0, 90000 ); ahora estado vale 2..
si vale dos -> mientras no se toque suelo no volverá a valer cero..




Ya te puedes imaginar como va a ser ;)


Toda la paranolla del control de un personaje se reduce a eso.


FreeYourMind

tienes alguna forma fácil o función de mapear un grafico irregular (con varios shape's de tipo LINE por ejemplo) para que colisione con otro objeto con todas sus partes distintas de su cuerpo (o sea que no sea una simple caja, circulo, trinagulo, etc, pero un grafico formado por varias formas). ?

Erkosone

He estado estudiando este tema, es quizá uno de los mas complejos, todavía no tengo nada que funcione, pero tengo algunas ideas sobre como hacerlo, la principal idea es basarme en un tipo de formas irregulares, las creadas con lineas, ya puede ser el gráfico lo complejo que sea, si está hecho a base de vertices el algoritmo debe funcionar.


Se basa en un scanner de contorno mediante la 'tortuga de papert', se almacena todo el contorno de la imagen en una lista dinámica de vectores simples [ X / Y ] para luego reescanearla con el algoritmo de la linea clásico e ir sacando la lista final de segmentos mediante una comprobación simple de trayectoria.


La idea la tengo clara pero todavía no me he puesto a montarla, aunque en realidad es bastante simple en concepto.


En lo que he invertido bastantes horas es en crear todo el API de getters/setters para la librería, tanto de velocidad, posición, angulo, constraints etc etc..  me falta por implementar el collision_matrix[] que no es mas que una matriz de estados de colisión en tiempo real que tenía implementada para mi librería de física, pero viendo que la chipmunk ya maneja esto directamente tengo que modificar los getters del api para que sea compatible.


Lo del algoritmo de vectorización de imágenes "por segmentos" es uno de mis pendientes que tengo que ponerme un dia de estos cuando todo lo que tengo ahora mismo entre manos esté terminado, pero la idea es esa que te comento.




Por si quieres indagar tu mismo un poco sobre el tema te explico un poco mas profundamente como debería ser:
- El primer paso es cargar una imagen y mediante map_get_pixel() "disculpadme si llamo mal a alguna función, uso muchos divLikes y aveces me confundo", pues eso, se coloca el cursor en el centro de la imagen "cursor virtual claro" y se comienza a subir hasta encontrar un pixel sin color.
- El segundo paso es utilizar el algoritmo conocido como "pappert turtle" para barrer el contorno pixel a pixel, esto ya lo tengo implementado y funciona perfecto.
- El tercer paso es que mientras la tortuga de pappert avanza se comprueba si la posición del vector actual es igual a la del vector inicial, si es así el escaneo de contorno ha terminado.
- El cuarto paso es, habiendo guardado todos los vectores "aclaro que llamo vector a un campo de una estructura X/Y como lo sería un c_point" que la tortuga de pappert ha reconocido como "propiedad del contorno de la imagen" hay que hacer un segudo barrido, esta vez se parte de la lista de vectores creada anteriormente.


Este paso final debe hacer lo siguiente:
1 - Colocar el cursor en el primer vector de la lista.
2 - comprobar el angulo con el siguiente vector.
3 - avanzar una posición en la lista de vectores y comprobar que el angulo entre el primer vector y el angulo entre el segudo y el tercer vector son iguales "con una tolerancia mínima", si es así se trata de 3 puntos que están en la misma recta o segmento.
4 - seguir avanzando en la lista de vectores hasta encontrar un vector que se sale de la trayectoria de la recta..
5 - Se crea el segmento mediante la chipmunk con la posición inicial y la posición final del barrido actual.
6 - Ahora el segmento inicial es la posición donde termino el barrido anterior..
7 - vuelta a empezar.




Esto debería funcionar, seguramente será lento por que son muchas operaciones, lo mejor sería implementarlo en C pero vamos, que en lenguaje bennuGD tiene que funcionar por cojones ;)


La idea que tengo en mente es esta, es un scaner de contorno + un scaner de segmentos.

FreeYourMind

En realidad el ultimo port de Chipmunk trae el algoritmo ese para detectar la forma del grafico pero esta en fase beta, todavia no va perfecto, el cual se puede mejorar si alguien se quiere dedicar a el ya que viene el src y ejemplo prg con la ultima version.

Erkosone

Primer objetivo completado.


- Ya tengo el editor de archivos .cpt, las features son estas:


- Carga de imagenes en formatos standard png, bmp, jpg..
- Edición de puntos de control de forma totalmente visual y cómoda.
- Zoom, se puede ampliar la imagen y trabajar con el editor tranquilamente, esto es muy practico en mapas de scroll para dispositivos de reducida resolución.
- Color flip, se selecciona la herramienta del cuentagoatas y se hace click en un pixel de la imagen, se recoje el color, se abre la paleta y se selecciona un nuevo color, se hace click en la herramienta de color flip y voila.. se intercambian de color todos los pixeles de la imagen.
- Sprite CUTTER "un calco al del editor de Div2", se abre la herramienta de recorte de sprites y se hace click en un pixel con color diferente de cero, se hace click en "Sprite Cut" y ale.. el algoritmo de la tortuga de pappert recorre el contorno del sprite y lo exporta.
- .CPT options:
* Export as..
* Clear current list.
* Import.


Como veis aparte de servir para crear y editar archivos .cpt sirve para realizar algún trabajo extra con tilesets.




Comienzo el tema de las funciones de carga de escenarios y el port completo del API de mi lib de física para hacerlo compatible con la chipmunk, en cuanto tenga el ditor bien testeado y sin bug´s lo comparto.
Un saludo.

Erkosone

Vaya, leyendo todo el hilo de la chipmunk para bennuGD y viendo todo el trabajo que se ha invertido en esta librería me he quedado gratamente sorprendido, tenía la intención de montar algunas funciones para simplificar e integrar un poco la lib con el lenguaje bennuGD pero veo que esta librería está super integrada con el lenguaje, que bien!


Mis felicitaciones al autor, lo de que funcione de una forma tan próxima a los procesos no tiene precio.


Viendo que este trabajo está cojonudo me voy a poner a aumentar las capacidades del editor de escenarios y a montar ejemplos para que sirvan de plantilla para el que tenga curiosidad, realmente no esperaba que la chipmunk estuviera tan integrada con bennu.. me he llevado una muy grata sorpresa.


Gracias de nuevo al autor del port, es cuanto menos excelente.

Erkosone

#8
Avances:
- Ya tengo implementados los setters para mover a un objeto con absoluta y rigurosa suavidad!


* Estoy trabajando a tope en este proyectillo para simplificar al máximo el uso del gran trabajo que ha realizado el señor Prg, ya tengo una de las partes mas importantes montada y por suerte he conseguido aprender como funciona lo que ha hecho Prg, la suerte es que ha respetado el api oficial casi al máximo y esto ayuda mucho para continuar el trabajo jeje.


Un avance de una de las funciones que ya me funcionan a la perfección, la cuelgo por si alguien quiere usarla mientras completo todo lo demás.





function Physics_entity_add_velocity( float module_, float angle_ );
private
   cpVect velocidad_;         // velocidad a sumar a la actual de la entidad..
   cpVect velocidadActual_;   // velocidad actual de la entidad..
   float vx;
   float vy;
begin
   vx = module_ * cos(angle_);
   vy = module_ * sin(angle_);
   cpv( vx, vy, &velocidad_ );
   
   GetBody(father.lphysics.body,cp_c_v,&velocidadActual_);
   cpvadd(&velocidadActual_, &velocidad_,&velocidadActual_);         // Suma de velocidad actual mas velocidad a añadir..
   DEFBODYP(father.lphysics.body,CP_C_V,&velocidadActual_);         //Define la nueva velocidad de la entidad..
   return(0);
end






Osease, para que se vea la diferencia de código a picar entre la lib a pelo y el engendro que estoy montando "capa de abstracción", basicamente eso es lo que hay que teclear para mover un objeto, pero con el API de alto nivel que estoy armando basta con hacer esto:


if(key(_left)) Physics_entity_add_velocity( 2.0, 0.0 ); end
Esta linea suma 2 al vector de velocidad del cuerpo que pertenece al proceso que realiza la llamada a la función, creo que queda bastante simple XD.. los parámetros de la función son bien simples:
1 - velocidad.
2 - angulo.


La función ya descompone la velocidad pasada como MODULO|ANGULO a VX|VY y la aplica por punteros con el api original que hizo Prg.


Bueno.. sigo con esto.. haber si logro crear todo lo que tengo en la lista, creo que va a resultar algo bastante simple de usar jeje.
Un saludo.




Edito:


Para mover un objeto con los cursores:
si se pulsa la tecla izquierda:  Physics_entity_add_velocity( 2.0, 180000.0 );
si se pulsa la tecla derecha: Physics_entity_add_velocity( 2.0, 0.0 );
si se pulsa la tecla arriba: Physics_entity_add_velocity( 2.0, -90000.0 );
si se pulsa la tecla abajo: Physics_entity_add_velocity( 2.0, 90000.0 );




Para que se vea un poco lo que simplifica el API que estoy preparando.. esto es un proceso bola que se puede mover..





process test_object();
begin
   x = 100;
   y = 50;
   graph = g_ball;
   // Definición de las propiedades de este cuerpo: [ masa, elasticidad, fricción ].
   Physics_entity_build( 10.0, 0.9, 0.3 );
   loop
      if(key(_left))
         Physics_entity_add_velocity( 10.0, 180000.0 );      // parametros de velocidad: [ modulo, angulo ]
      end
      frame;
   end
end


Incomming..

Kalas

Woww!!! sorprendente!!!!! esto me ayuda a entenderlo mejor :D

Erkosone


alex

#11
buf, veo que lleva trabajo, yo en esto te podria ayudar poco, (no he visto funciones trigonometricas todavia, aujnque se mas o menos que hace el seno y el coseno de un angulo). Una cosa en las lineas que haces el coseno y seno funcionan en milesimas de angulo??? pag 293 manual de osk,
QuoteCOS(NUMERO)
Esta función, definida en el módulo "mod_math", devuelve el coseno de un ángulo dado en milésimas de grado (la
unidad estándar para especificar ángulos en Bennu). El resultado será un número en coma flotante entre -1 y 1.

Erkosone

Jodo!! ya tengo portados los brakers!


Esto me preocupaba por que en mi lib eran bastante ineficaces y lentos, pero directamente multiplicando vectores literalmente la cosa vuela.


Se trata de un set de funciones que permiten el frenado dinámico por porcentaje, están diseñadas especialmente para juegos tipo plataformas donde controlamos normalmente un personaje y al soltar los mandos vemos claramente que la inercia no hace lo que exactamente deseamos.


Estas funciones son tan simples como esto:  Physics_entity_brake( float percent_ );


El parámetro debe comprender valores de entre cero y 100, siendo 100 un frenado en seco, y valores menores representaran frenados desde muy muy suaves hasta lo bruscos que necesitemos.


Esto se anima XD..  ahora podremos de una forma muy simple al mas puro estilo DIV frenar un objeto "de una forma increiblemente suave" sea cual sea su masa y/o el valor de inercia seteado por la lib, digamos que es una función que aplica un decremento de inercia por si misma.

Erkosone

Hola alex, uso el seno y coseno con FLOATS, de esta manera mantengo la consistencia de los tipo de datos.
Si se usase con INT´s el resultado cambia ;)

alex

Quote from: Erkosone on January 18, 2013, 06:13:55 PM
Hola alex, uso el seno y coseno con FLOATS, de esta manera mantengo la consistencia de los tipo de datos.
Si se usase con INT´s el resultado cambia ;)
Pero son en milesimas de grado entonces deberias multiplicar por 1000 en la funcion... igual no te he entendido muy bien, el caso es que yo e cai justo ahi, que programando una funcion para situar una camara le daba valores como 180, y no entendia porque no se movia, hasta que puse 180000 xD.
PD: Se me fue la olla, te puse angle y no las funciones.