Gravedad

Started by zelda99, November 19, 2012, 11:21:43 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

zelda99

Hola a todos, estoy empezando a usar el lenguaje y ya tengo mis primeras dudas, en concreto seria la manera de implementar gravedad a un proceso (para el salto), vi un ejemplo en el manual pdf de osk pero no me quedo muy claro, me gustaria que tenga aceleracion y desaceleracion (para hacerlo mas realista). quiza alguien tenga algun ejemplo a mano?... bueno eso es todo espero alguna respuesta gracias

KeoH

Implementar algo que parezca a la gravedad parece facil pero no lo es xDDD si tienes el BennuPack instalado busca el juego de EEEEEKK EEEKKK OOOOKKK .. q tiene un sistema para el salto de mono muy chulo. Te marearás buscando la parte del codigo exacto pero asi aprendes a leer codigo de otros y puedes sacar ideas. Si te ves que te supera y es demasiado complejo para tí, no tengas prisa. Prueba cosas mas sencillas.

zelda99

si, se que es complicado, por las formulas y demas, mucha fisica para que quede bien. voy a mirar el juego que mencionas, gracias

panreyes

Honestamente, soy malísimo en matemáticas y no tengo ni idea de programar físicas. Pero no hay que saber demasiado o ser un genio para conseguirlo :)


Pégale un vistazo a este código simple.
http://www.pixjuegos.com/descargas/nyan.rar

Futu-block

La gravedad practicamente se resume en una elipse, asi que toca matematicas con seno coseno in tangente...

Si nos ponemos a analizar la gravedad de algo lanzado hacia arriba (un tio saltando es lo mismo ;) ) al principio la fuerza aplicada es muy grande pero vá reduciendo gradualmente u de movimiento no lineal, hasta que llega a un punto cero donde los valores se invierten...

te hago un esquemita y en cinco minutillos te lo cuelgo ;)

Futu-block

Aqui tienes el ejemplo, al aumentar el radio el valor del seno aumentará de forma gradual en relacion a la circunferencia


Ahora lo que deves hacer es no avanzar en x



gecko

La solucion de laghengar es la más simple. Y si usas floats, o la local RESOLUTION, podes darle mucha suavidad al movimiento.
Torres Baldi Studio
http://torresbaldi.com

Erkosone

Buenas, me permito contestar para recomendaros algo ya que en estos ultimos meses he estado desarrollando una pequeña librería de física vectorial con velocidad, gravedad, colisiones, delta_time y colisiones de objetos enlazados por constraints etc etc..


La gravedad no es mas que un vector "tanto en la realidad como en la programación", no la mires como una elipse ni como un "apaño" para tu programa, mira a la gravedad como lo que es, algo que te empuja en una dirección hasta que toques un suelo ;)


Mi recomendación es que te pares una hora a estudiar los teoremas de un señor llamado "Verlet" en cual describe un sencillo sistema para implementar un mecanismo de física realista con calculos para nada complejos.


Te doy una pista sobre la gravedad, en un programa tienes que expresarla de igual manera que la expresa box2d o chipmunk, bueno.. hay 2 formas de expresarla, la mas sencilla de las dos y que luego te va a servir para poder calcular todo lo demás "sin complicaciones" es esta:


aGravity = 90000.0;
vGravity = 0.098;


Que es eso? dos simples variables "globales" que expresan el angulo de la gravedad y el valor de su aceleración.
Si lo haces así luego podrás simplemente cambiar el angulo de la gravedad y que los objetos floten etc etc..


Como añadir la gravedad a un proceso?
Es lo mas simple del mundo, dentro de su bucle 'LOOP':


x += vGravity * COS(aGravity);
y += vGravity * SIN(aGravity);


Mola no? prueba a cambiar el angulo de la gravedad y verás como puedes orientarla hacia donde tu quieras..


Como parar la gravedad o simplemente anular su efecto?
Sencillo también:
fi(NOT toco_suelo)
//.. aquí el código anterior..
end


La variable 'toco_suelo' simplemente debe estár en TRUE/FALSE en función de si ese proceso toca un suelo/plataforma o no.


El resultado de este sistema de gravedad lo puedes ver en este vídeo, el programa no usa ninguna librería de física, bueno si que una una. la que yo me he programado ;)
Así que te aseguro que este es un buen punto de partida.
Un saludo.


http://www.youtube.com/watch?v=tL0ti2YXdK8

Erkosone

Ahora salgo a comprar algo.. cuando vuelva si no se me la cabeza con otra cosa te explico también un tema importante, las 4 propiedades que tiene que tener cualquier objeto para que se le pueda aplicar física de Verlet y te copio y pego una función llamada updateVector() para que no tengas ni que hacerlo tu.. esta función es la encargada de convertir posición en velocidad y apartir de ese momento para mover a un personaje ya no tendrás que hacer mas  x++  si no que tendrás que hacer vx_ += 0.1


El resultado será el mismo pero con un sistema de fricción automático, esto suavizará enormemente todos los movimientos dejandolos a la altura de cualquier lib de física.

SplinterGU

muy bueno erkosone, felicitaciones...

esto esta en bennugd o en gemix (que a decir verdad el otro dia entre a su pagina y me puse a ver unos videos de los juegos que hay hechos con el o en desarrollo y debo reconocer que se mueve bien) ?

piensas compartir la libreria de fisica que has hecho?
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Erkosone

Gracias Splinter, la verdad es que me ha costado ponerme a estudiar unos meses para poder montarla, he tenido que aprender "pero de verdad" trigonometría, geometría, física dinámica, cinemática, cinemática inversa, deformación de cuerpos elásticos.. y para el tema de la respuesta de las colisiones ya ha sido el no va mas, es un tema apasionante para mi y en su día pensé que si lograba hacer una librería por mi mismo aunque fuera mínima con un escenario vectorizado a lineas y un motor de física realista para una lista de objetos sencillos, entonces cuando me pusiera ya en serio a usar box2D o chipmunk sería capaz de sacarle todo el potencial a estas librerías ya de categoría superior.


Pues el vídeo que se ve exactamente está programado en gemix, pero el código es completamente portable a BennuGD y la idea es compartirlo por supuesto, es open source completamente y lo mejor de todo es que está programada en el propio lenguaje de scripting, con lo que es completamente personalizable y expandible.


Lo del lenguaje en si es lo de menos, me puse como meta personal que la lib no dependiera de ningúna de las funciones de ningún lenguaje, así es portable desde C a pelo hasta cualquier otro lenguaje como lo es BennuGD o gemix.


Estos días un colega ha estado testeandola y la está usando para un juego, le ha añadido varias propiedades que no tenía y me ha sugerido de añadir algunas mas que todavía no tiene, en cuanto tenga un poco de tiempo la traduciré a bennu por que es cosa de 30 minutos.


Lo mejor de todo esto no es que sea una lib muy muy poderosa, si no mas bien que está con todo el código a la vista y creo que se entiende bastante bien, así que cualquiera puede añadirle lo que necesite y no va a tener ningún problema en que no sea compatible con cualquier plataforma ;)


Ahora mismo tengo 2 librerías por separado, la que uso para juegos que dispone de:
- Gravedad vectorial.
- Velocidad por escalares con signo.
- Objetos tipo Circulo.
- Sistema de inercia real "en un rebote se calcula el llamado 'momentum' o momento de inercia" y todo se resuelve en base a las teorías de verlet aplicadas a cuerpos de masa conocida.
- Sistema automático de asignación de masa a un objeto. "en función de su radio".
- Sistema automatizado de detección de colisión entre "circulo - segmento".
- Sistema automatizado de detección de colisión entre "circulo - circulo".
- Sistema de transmisión de energía entre objetos en un choque "lo mismo que el momentum pero entre objetos tipo circulo".


Y lo mas complejo de todo esto:
- Sistema encargado del DELTA_TIME o también llamado TIME_STEEP que parte 1 frame en n' subframes y soluciona las colisiones con una precisión muy elevada ya que objetos de reducido tamaño podrían atravesar a otros objetos también pequeños y no sería posible detectar la colisión, este sistema precalcula n' veces toda la física necesaria para que ningún objeto atraviese a otro.




Y luego tengo el segundo motor que es específico para animación por cinemática inversa, trata sobre unir puntos para formar figuras complejas, todo el sistema que calcula el centro de gravedad, la inercia, la fricción y estas cosas ya lo tengo terminado, ahora me falta la resolución de colisiones que es algo realmente duro, he hecho algunas pruebas con exito pero de verdad que tengo que estudiar un poco mas para dominar tal cosa, es realmente un tema complejo, si logro realizar esto con exito pues ya tendré una librería de física completa, pero es el paso mas complicado de todos, y aunque he resuelto parte del problema y en casos concretos con 2 o 3 objetos funciona, con mas objetos es realmente caótico y tengo que repasar los calculos que he implementado en esa parte "respuesta de colisión entre objetos complejos formados por vectores interconectados por constraints".
Suena feo XD.. realmente es duro de entender.

KeoH

Pues por lo que cuentas suena estupendamente!! Felicidades porq sé que es un tema complejo. Estoy deseando echarle mano a esa libreria que puede aportar cosas estupendas. Animo.

Erkosone

#12
Bueno.. a lo que iba, la función de la que hablaba es esta:




function updatePoint( x );
private
    float dx;
    float dy;
begin
    dx = ( (nodos
  • .x_ - nodos
  • .oldx_) * 1.0 / (float)timeSteep);
        dy = ( (nodos
  • .y_ - nodos
  • .oldy_) * 1.0 / (float)timeSteep);
        nodos
  • .oldx_ += dx;
        nodos
  • .oldy_ += dy;
        nodos
  • .x_ += friction * (dx + vGravity * cos(aGravity));
        nodos
  • .y_ += friction * (dy + vGravity * sin(aGravity));
        return(0);
    end



    Es muy sencilla de entender pero la explico a fondo para que el concepto de como usarla quede claro:
    - Basicamente en mi caso y para mi motor he creado una estructura llamada nodos.


    En realidad es un typedef pero eso no viene al caso..


    Vale, que hace esta función?
    - Hablando en general actualiza la posición de un vector, y eso para que me sirve en un juego donde no hay un motor de física todavía?


    Vale.. veamos de convertir esta función para que sea aplicable a un simple proceso.




    Teoría:
    - Para empezar tenemos que saber que mover por pantalla a un objeto dependiendo de una velocidad es un completo error, aveces cuando uno no sabe como hacerlo pues lo hace así, pero no es la mejor solución, simplemente por que estamos pasando por alto unos datos que son muy importantes, la posición relativa anterior y la posición relativa actual, que entre las dos generan la posición realtiva del siguiente frame.




    Entonces? que debe tener un proceso para tratarlo como si formara parte de los elementos de un motor de física?
    Un proceso debe tener 4 variables LOCAL primordiales para hacer las cosas bien, y para que no estemos limitados a la imprecisión de los datos tipo INT deben ser "como mínimo" del tipo FLOAT.


    Tales variables son:
    float oldX_
    float oldY_
    float x_
    float y_


    Que representan estas variables?


    oldX_ y oldY_ indican la posición que tenía el objeto "proceso en este caso" en el frame anterior,
    X_ e Y_ indican la posición actual que tiene el proceso en el frame actual.




    También tenemos que disponer de una variable GLOBAL llamada: 'FRICTION' y tiene que ser "como mínimo" del tipo float.
    Para que sirve esta variable?
    - Simple, será la encargada del control de inercia de los objetos, dado que en el bucle de los objetos que hagan uso de este sistema que estoy explicando existirá la llamada a la función updatePoint() en ella será donde se aplique la denominada "fricción" que será la encargada de frenar con mayor o menor suavidad a los objetos.


    Que valores debe tener la variable FRICTION?
    para un valor de 1.0 no existirá fricción, osea, los objetos no perderán parte de su inercia/enegía durante el tiempo
    para un valor de 0.0 la fricción será maxima y los objetos no serán capaces de moverse.
    Esto nos da un amplio rango de valores para experimentar y observar los resultandos, customizando de esta manera el comportamiento de nuestra pequeña física ingame.




    Y todo esto para que me sirve?
    - Simplemente para calcular con absoluta precisión la velocidad de desplazamiento del proceso "entiéndase que nos referimos al gráfico del proceso".


    Vale.. y como debe un proceso gestionar su movimiento según esta teoría?
    - Simple, como en este ejemplo:
    Process pepito();
    begin
    graph = ...
    loop

    // ejemplo simplisimo de movimiento..
    if(key(_left)) X_ --; end
    UpdatePoint();
    frame;
    end
    end




    Con esto tenemos que si pulsamos el cursor izquierdo la variable LOCAL 'X_' disminuye.. simple.
    También vemos que se llama a la función UpdatePoint();


    Como debe quedar la función para que funcione con procesos y aplique la gravedad automáticamente?



    function updatePoint();
    private
        float dx;
        float dy;
    begin
        dx = father.x_ - father.oldx_;
        dy = father.y_ - father.oldy_;
        father.oldx_ += dx;
        father.oldy_ += dy;
        father.x_ += friction * (dx + vGravity * cos(aGravity));
        father.x = father.x_;
        father.y_ += friction * (dy + vGravity * sin(aGravity));
        father.y = father.y_;
        return(0);
    end




    Como se puede ver, la función procesa la perdida de inercia, las velocidades, aplica la gravedad global del mundo al objeto, y finalmente actualiza la posición del proceso que la ha llamado.


    Espero que os sea de ayuda ;)




    Haaa!! se me olvidaba.. como unica precaución para que los objetos no salgas disparados al inicio se debe especificar en el proceso lo siguiente:
    En el momento de asignar un valor inicial a X y a Y se debe hacer así para que el objeto no tenga ningúna velocidad inicial:
    Supongamos que se quiere iniciar un proceso en la posición de pantalla x = 100, y = 200;
    Se debe hacer así:


    x = x_ = oldx_ = 100;
    y = y_ = oldy_ = 200;


    Esto solo en la inicialización, por que como ya habréis deducido, tanto la velocidad, la inercia, la fricción o energía, y la gravedad se calculan en base a los valores de X_/Y_ y oldX_/oldY_, la función UpdatePoint() ya se encarga de actualizar las X/Y reales del proceso, así que cualquier modificación de posición debe hacerse siempre sobre las variables:
    X_
    Y_


    Ahora ya si, a disfrutarlo ;)
    NOTA: Todo esto lo estoy contando de cabeza, si alguien lo prueba y tiene algún problema que no tenga reparo en comentarlo por aquí mismo, encantado le hecho una mano.

Erkosone

Así leyendo lo que he puesto creo que me he pasado XD..


Solo preguntaban por la gravedad y me he liado a escribir sobre un sistema "básico" pero completo, esto engloba las propiedades:
Inercia.
Fricción.
Gravedad "vectorial".
Velocidad desatendida.


Pero vaya.. que como info en general mola mucho ver como desde una simple función se puede agrupar todo el control de tantos comportamientos que yo mismo y supongo que casi todos nosotros nos hemos matado a montar a mano durante muchos años por separado en todos los objetos de un juego..


Merece la pena completamente usar este sistema u otro similar a este en concepto, con esto nos despreocupamos de casi todo lo relacionado con el movimiento de un juego sencillo.

SplinterGU

una pregunta, o quizas tambien una sugerencia...

tu dices que la fisica se basa en gravedad y angulo de gravedad... pero no seria mejor poder definir objetos con (centro de) gravedad y que los demas objetos interactuen con este de acuerdo a la fuerza de gravedad que este objeto tiene y a la distancia que estan (obviamente el angulo se calcularia solo)?

por ejemplo, defino un objeto tipo planeta tierra (su centro) y la fuerza de su gravedad, ahora empiezo a poner objetos mas chicos, que seran atraidos por este centro, hasta encontrar un suelo, segun la distancia de este suelo se modifica automaticamente el angulo y la fuerza con que interactuan... lo mismo podria tener un objeto tierra y un objeto luna, ambos con su gravedad y los objetos que se aproximan a uno u a otro, seran afectados por la fuerza de gravedad de estos objetos.

no seria mejor que la cosa sea asi? digamos que solo cambiaria lo del angulo que seria calculado automaticamente...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2