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.

alex

#15
Vale, me autocorrijo, no mire bien el codigo, en milesimas de grado con coma flotante.


Y parece que no se leer que lei despues que el parametro era en coma flotante. Sorry.

Erkosone

Bueno.. me voy al curro.. la tarde ha cundido bastante jeje..


Lo que ya tengo funcionando:
- Physics_world_set_gravity( float module_, float angle_ );
- Physics_world_set_timestep( delta_time_type_ );
- Physics_entity_build( float masa, float elasticFactor, float friccion );
- Physics_entity_add_velocity( float module_, float angle_ );
- Physics_entity_add_vx( float module_ );
- Physics_entity_add_vy( float module_ );
- Physics_entity_brake( float percent_ );
- Physics_entity_brake_x( float percent_ );
- Physics_entity_brake_y( float percent_ );


Esta noche cuando llegue del curro comenzaré con los getters y setters de velocidad, serán algo como esto:
- Physics_entity_get_velocity( float * module_, float * angle_ );
- Physics_entity_get_vx();
- Physics_entity_get_vy();
- Physics_entity_set_velocity( float module_, float angle_ );
- Physics_entity_set_vx( float vx_ );
- Physics_entity_set_vy( float vy_ );


Esto servirá para hacer algo como esto:
if( Physics_entity_get_vx() > 5.0 ) Physics_entity_set_vx( 5.0 ); end


Así se puede controlar de una forma muy simple la velocidad máxima de un objeto, por ejemplo un personaje que se mueve por un escenario o cualquier cosa vaya.

Prg

#17
Hola amigo. No se si por chipmunk te refieres a mi mod_chipmunk, creo que sí.

Mira, tengo un código de aproximación poligonal, te podría servir para convertir un gráfico en un conjunto de lineas. Lamentablemente no he podido hacerlo en c. Es un código de mi tesis que pensaba usar, pero no he tenido tiempo.

Comparto este código contigo y la explicación de él (pdf adjunto, comienza en las últimas lineas de la primera página). Está escrito en matlab, espero conozcas el lenguaje.

function aproxPolig()
    clc; close all;
    set(0,'RecursionLimit',1500);
    im = im2gray(imread('05.png'));
    im = bwmorph(im,'remove');
    im = bwmorph(im,'skel');
    [vi,vj]=vertices(im);
    [ir,jr]=aproxP(vi,vj,5);
    imshow(im);
    %line([jr jr(1)],[ir ir(1)]);
    hold on
    plot([jr jr(1)],[ir ir(1)],'*g',[jr jr(1)],[ir ir(1)],'-y');
    hold off
    fprintf('cantidad de puntos = %d\n',length(jr));
end

%recorre la imagen de bordes agregando los vértices a un vector
function [ai aj]=vertices(im)
    [i,j]=find(im,1);
    ind=1;
    while (1)
        ai(ind)=i;
        aj(ind)=j;
        im(i,j)=0;
        ind=ind+1;
        if (im(i,j+1)==1)
            j=j+1;
            continue;
        end
        if (im(i+1,j+1)==1)
            j=j+1;
            i=i+1;
            continue;
        end
        if (im(i+1,j)==1)
            i=i+1;
            continue;
        end
        if (im(i+1,j-1)==1)
            j=j-1;
            i=i+1;
            continue;
        end
        if (im(i,j-1)==1)
            j=j-1;
            continue;
        end
        if (im(i-1,j-1)==1)
            j=j-1;
            i=i-1;
            continue;
        end
        if (im(i-1,j)==1)
            i=i-1;
            continue;
        end
        if (im(i-1,j+1)==1)
            j=j+1;
            i=i-1;
            continue;
        end
        break;
    end
end

function [ci,cj]=centroide(vi,vj)
    ci=round(mean(vi));
    cj=round(mean(vj));
end

function d=fdist(ix,iy,fx,fy)
    d=sqrt((ix-fx).^2 +(iy-fy).^2);
end

%x3,y3 son las coordenadas del punto
function d=rectdist(x1,y1,x2,y2,x3,y3)
    up=(y1-y2);
    down=(x1-x2);
    %tam=length(x3);
    %d=zeros(1,tam);
    %for z=1:tam;
    if (up==0)  %la misma y
        d=x3-x1;
        return;
    end
    if (down==0)  %la misma x
        d=y3-y1;
        return;
    end
    m=up/down;
    b=y1-(m*x1);
    d=abs(m.*x3-y3+b)./sqrt(m^2+1);
    %end
end

%vii lista de coordenadas en i
%vij lista de coordenadas en j
%ir lista resultado en i
%jr lista resultado en j
%umb umbral de error para limitar la fragmentación en los trozos.
%ind se marcan con 1 los  puntos que pertenecen al cuerpo poligonal
function [ir,jr]=aproxP(vii,vjj,umbb)
global ind;
global vi;
global vj;
global umb;
%global cont;
%cont=0;
    vi=vii;
    vj=vjj;
    umb=umbb;
    clear vii;
    clear vjj;
    clear umbb;
    [ci,cj]=centroide(vi,vj);
   
    ind=zeros(1,length(vi));
   
    d=dist(ci,cj,vi,vj);
    [y,inc]=max(d);         %toma el índice del punto más alejado al centroide
   
    ind(inc)=1;             %marca el punto más alejado al centroide como parte del cuerpo poligonal
   
    d=fdist(vi(inc),vj(inc),vi,vj);
    [y,fin]=max(d);         %toma el índice más alejado punto anterior
   
    ind(fin)=1;             %marca ese punto como parte del cuerpo poligonal
   
    recursApro(inc,fin);        %llama recursividad para dividir por cuerpos poligonales usando la linea del índice inc al fin que son los índices del principio y final de la primer linea
    recursApro(fin,inc);
   
    %rs(ind)=1;
    ir=vi(find(ind));       %las i del resultado son aquellas que se han marcado como parte de la aproximación poligonal
    jr=vj(find(ind));

end

%inic índice inicial para la linea en que comenzará la recursividad
%fin índice final de la linea para comenzar la recursividad
%umb umbral de error para limitar la aproximación poligonal
%si fin<inic  se debe hacer un buffer circular para esto xxxoooooxxx con x
%---los puntos de búsqueda
%ind almacena con 1 los puntos que forman parte del resultado
function recursApro(inic,fin)
global ind;
global vi;
global vj;
global umb;
%global cont;
%cont=cont+1
    if (fin<inic)   %buffer circular
        tm=length(vi);
        d1=rectdist(vi(1),vj(1),vi(fin),vj(fin),vi(1:fin),vj(1:fin));
        d2=rectdist(vi(inic),vj(inic),vi(tm),vj(tm),vi(inic:tm),vj(inic:tm));
        [v i]=max([d1 d2]);
        %pause
        if (v>umb)
            if (i>fin)             %ajusta i al arreglo completo
                i=i-fin+inic+1;
            end
            ind(i)=1;
            if (i~=1)
                recursApro(inic,i-1);
            elseif(inic~=tm)
                recursApro(inic,tm);
            end
            if (i~=tm)
                recursApro(i+1,fin);
            elseif (fin~=1)
                recursApro(1,fin);
            end
        end
        return;
    end
    d=rectdist(vi(inic),vj(inic),vi(fin),vj(fin),vi(inic:fin),vj(inic:fin));
    [v i]=max(d);
    %pause
    i=i+inic-1;
    if (v>umb)
        ind(i)=1;
        if (i~=inic)
            recursApro(inic,i-1);
        end
        if (i~=fin)
            recursApro(i+1,fin);
        end
    end
   
end


Si lo escribes en c, no olvides compartirlo para poderlo agregar en la librería. Creo que siempre compartí el código fuente de Chipmunk, si también quieres trabajar sobre él.

Saludos, espero pronto continuar con el proyecto chipmunk... Saludos

pd: espero entiendas mi redacción. No he revisado coherencia detenidamente y esta versión de mi documento no la han revisado mis asesores así que ello no tienen la culpa si no se entiende... je je XD ... De cualquier forma creo que sí te servirá...
[/code]
en humos puedes mover la camara con los cursores. es necesario para los niveles a partir del dos :)

Erkosone

Vaya, gracias Prg, y si, lo que ando haciendo es una simplificación de todo tu trabajo.


En esencia es una colección de funciones para hacer todo lo que solemos hacer en un juego de scroll o mode7 pero sin tener que tocar funciones a tan bajo nivel que funcionan a la perfección pero para alguien sin experiencia seguro que se espanta pronto al ver el código necesario jeje.


Por cierto, he visto que la librería está muy integrada en el lenguaje BennuGD, y quisiera hacerte algunas sugerencias para ella, cuando saque un rato si lo ves correcto me gustaría abrirte un post con un par o tres de cosillas que puede que ayuden bastante a simplificar mas todavía el uso de la 'mod_chipmunk' ;)


Sobre el source que me pasas pues no, no se mathlab, pero todo es ponerse, seguramente leyendo el documento que lo acompaña y entendiendolo sea capaz de entender tu idea, haber si termino los primeros pasos de todo esto que es dejar un API muy simplificado y funcionando, y ya los siguientes pasos son este que comentas y que comentaba anteriormente FreeYourMind y el de crear un archivo para los escenarios, tengo un formato creado y un editor ya funcionales pero quiero añadirle algunas caracteristicas mas para que simplemente el archivo sea una lista de objetos vectorizados y no solo una lista de puntos de control la cual hay que tratar desde el código.


En cualquier caso muchas gracias por compartirlo, le hecharé un ojo lo antes posible ;)
Y gracias también por tu trabajo, está cojonudo.

Erkosone

Bueno.. misión cumplida!


Ya están implementadas todas las funciones que he comentado, ahora le toca el turno a los segmentos y a las colisiones.. haber si este fin de semana termino de montar esto y cuelgo un zip con unos cuantos ejemplos de uso, creo que a los expertos les podrá resultar insultante XD.. pero a los novatos sin experiencia quizá les abra una nueva puerta por explorar!


Os dejo un .ZIP con lo que tengo hasta ahora por si alguien quiere ojearlo, todavía está verde pero se ve la idea de todo esto ;) 


Ahora si, un zip para probar:

Ran

Lo he probado y va muy bien, la física ya es bastante buena, a veces se queda dando botitos muy pequeños no se si es por la física que tienes configurada, pero por lo demás va muy bien :D

Erkosone

AVANCES:
- Physics_scenario_load( string fileName_ );
- Physics_scenario_build();


Bueno.. pues después de pelearme con la WIKI de bennuGD unas cuantas horas "gracias a quien la haya redactado, es un recurso muy valioso", pues eso, que después de estár horas leyendo la documentación sobre split() y el modulo regex ya he logrado completar el segundo objetivo, el poder cargar un par de archivos generados desde mi editor, uno con extensión png y el otro con extensión cpt.


El resultado es un escenario vectorizado en scroll jeje.. que por cierto.. es una delicia para mis ojos ver como funcionan las colisiones, son mas que perfectas y suaves.
Voy a preparar un nuevo ZIP con una muestra de como queda el asunto por si alguien siente curiosidad.


Todavía tengo que simplificar mas la cosa pero esto ya es algo que pinta bien ;)

Erkosone

Test de ejemplo:
- Personaje controlable.
- Escenario vectorizado en modo scroll.


Teclas:
- cursores LEFT | RIGHT | UP para desplazarse.
- SPACE para frenar al personaje.


A la pregunta: Lo veis fluido? que me contestáis?


Erkosone

#23
Vídeo con pruebas de performance del API, he hecho un poco el burro creando procesos para probar hasta que punto es funcional "sin ralentización" esto, los resultados iniciales son bastante satisfactorios  :)


http://www.youtube.com/watch?v=38D4CmlasNk

Ran

Joder es la leche! por qué la bola queda flotando en vez de tocar el suelo? la fisica es muy buena! tengo ganas de probarla con algun juego ya :D

alex

Mi comentario igual te ofende un poco......   "MENUDA FISICA!!!" xDDD

Lo de que se ralentiza, no he percibido nada, me ha parecido a la misma velocidad todo.
Una pregunta, son bolas lo que has puesto, pero las colisiones te las captura en hexagonos, o eso lo puedes hacer más manual???

PD: estaria guay, (que yo he visto muchos videos de esos, sin embargo no se como se hace), creo que es un programa que te captura la tecla (o si es el raton tambien) que pulsas, asi poder ver un poco con el codigo que has dejado como va...

PD2: siento no haber mirado el zip de antes, si que esta muy curradisimo segun he mirado el codigo, pero no lo he podido probar, estoy en linux, y no tengo instlada la lib (soy un vago para compilar e instalar cosas manualmente xD)

Erkosone

He probado con 700 pelotas y ni se inmuta jeje.. que pasada.. estoy flipando.. la mod_chipmunk funciona muy bien.


Gracias por los comentarios, pero el mérito de todo esto antes que mio es de Prg que se ha currado la librería mod_chipmunk y la ha integrado jeje, yo solo estoy haciendo que sea "mas sencillo" su uso pero todo se basa en su trabajo.


Sobre el código, pues es este:



process Personaje(x,y);
begin
   ctype = c_scroll;
   scroll.camera = id;
   graph = g_ball;
   size = 20;
   // Definición de las propiedades de este cuerpo: [ masa, elasticidad, fricción ].
   Physics_entity_build( 10.0, 0.1, 0.3 );
   loop
      if(key(_left))
         Physics_entity_add_velocity( 2.0, 180000.0 );      // parametros de velocidad: [ modulo, angulo ] aplica una fuerza hacia la izquierda.
      end
      if(key(_right))
         Physics_entity_add_velocity( 2.0, 0.0 );         // parametros de velocidad: [ modulo, angulo ] aplica una fuerza hacia la derecha.
      end
      if(key(_UP))
         Physics_entity_add_velocity( 5.0, -90000.0 );      // parametros de velocidad: [ modulo, angulo ]   aplica una fuerza hacia arriba.
      end
      
      if(key(_SPACE))
         Physics_entity_brake(10.0);                  // Freno en un 10%/frame a la entidad.
      end
      
      if(Physics_entity_get_vx() > 200.0)                  // Si supero la velocidad en X..
         Physics_entity_set_vx(200.0);                  // la limito..
      end
      if(Physics_entity_get_vx() < -200.0)               // Si supero la velocidad en X..
         Physics_entity_set_vx(-200.0);                  // la limito..
      end
      frame;
   end
end


Creo que se entiende bien de un vistazo rápido y como ves el API es de muy alto nivel, te despreocupas de todo lo que sucede por debajo, solo hay que emplear esfuerzos en hacer el juego, que de eso se trata al fin y al cabo  ;D [size=78%].[/size]


Ahora mismo estoy programando el editor de niveles para este API, la cosa es tan sencilla como generar el mundo del juego desde un programa que estoy haciendo llamado "SCENARIO" y luego simplemente lo cargas con:  Physics_scenario_load( string fileName_ );  con esto ya tienes un escenario "scroll" en marcha con la chipmunk con todas las paredes suelos techos y demás cosas que son el horror de programar a mano con una calidad igual a la de la chipmunk.


Haber si termino el editor, lo había preparado para trazar lineas solamente.. pero he visto alguna limitación con este sistema tan simple, y al final me he decidido a crear algo currado, digamos que estos serán los pasos para crear un scroll para bennuGD con mod_chipmunk en este API:


1 - Abrir el editor SCENARIO y hacer click en NEW SCENARIO.
2 - Click en NEW OBJECT.
3 - Mediante la herramienta automática de lineas interconectadas entre si se hace click en los vertices de un objeto estatico del scroll "que se tendrá en pantalla a la vista".
4 - Click en SAVE OBJECT.


Y así para todos los objetos estaticos del escenario, luego CLICK en SAVE SCENARIO y ale.. lo cargas desde bennuGD y listos, no hay que preocuparse de nada mas, todo se configura solo para que funcione.


El tema es que quiero que los escenarios luego sean editables y tal.. no solo un simple "test", así que ando diseñando la estructura del programa y la estructura del archivo .SCN, cuando esté terminado te aseguro que crear un juego de scroll con física será cuestión de 1 minuto 2 como mucho.

Erkosone

AVANCES:
- Editor de escenarios completado  8)


Ahora ya tengo el API base y la herramienta para crear escenarios jejeje... en breve un vídeo con un tutorial sobre como crear un juego desde cero con todo esto y las descargas de todo en un pack.
Un saludo.

Ran

Joer como suena eso! que ganas de verlo!

Erkosone

Buenas, Prg si pasas por aquí me gustaría hacerte una consulta, cuando uso la función addInanimateShape() hay alguna forma de setearle el collisionType a ese shape?


He empezado a montar los collision hadlers para el API que ando haciendo y no veo el sistema para setearle a las lineas del escenario el collisionType = 2, sabes como se debe hacer?
O tendría que usar otro tipo de objetos "no estáticos" para esto?