Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: quiero aprender en Octubre 24, 2017, 05:32:26 PM

Título: Delta time en salto[Resuelto]
Publicado por: quiero aprender en Octubre 24, 2017, 05:32:26 PM
Hola a todos.
Tengo un problema con el delta time a la hora de saltar. He encontrado en la página: https://nikles.it/2017/gamemaker-tutorial/optimizing-collision-code/ una forma de optimizar el código de colisiones y va de maravilla lo recomiendo bastante y he conseguido agregar el delta time en velocidad horizontal pero no en velocidad vertical.

En el evento create del Delta time tengo esto: 
//Variables delta time
desired_fps = 30;
global.frame_delta = 30 / 1000000 * delta_time;


En el evento begin step:
global.frame_delta = desired_fps / 1000000 * delta_time;

Y funciona el delta time.

En el evento jugador:
/***************************************************
  Vertical Movement
***************************************************/
if yVel != 0
{
    yVelSub    += yVel;
    vyNew       = round(yVelSub);
    yVelSub    -= vyNew;
    var ydir    = sign(vyNew)
   
    // Check our direction (up or down)
    if ydir == 0
        var coll = noone
    else if ydir == 1
        var coll = collision_rectangle(bbox_left, bbox_top, bbox_right, bbox_bottom + vyNew, obj_block, true, false)
    else if ydir == -1
        var coll = collision_rectangle(bbox_left, bbox_top + vyNew, bbox_right, bbox_bottom, obj_block, true, false)
    // If there's a collision, move to contact
    if coll
    {
        while (!collision_rectangle(bbox_left, bbox_top + ydir, bbox_right, bbox_bottom + ydir, obj_block, true, false))
        {
            y += ydir;
        }
       
        // Once in contact, set the speeds to 0
        vyNew   = 0
        yVel    = 0
    }
    else // If no contact, move freely
        y += vyNew;
}
}

on_ground = collision_rectangle(bbox_left, bbox_bottom +1 , bbox_right, bbox_bottom +1, obj_block, true, true)

if !on_ground{
    yVel += 0.3 * global.frame_delta;
}
else{
    if keyboard_check(vk_up){
        yVel = -9.5 * global.frame_delta;
    }
}


A la hora de aplicar por ejemplo 10 fps no es proporcional el salto de 60 fps, ya intente de varias formas pero actualmente lo tengo así.

Gracias por su ayuda.
Título: Re:Delta time en salto
Publicado por: quiero aprender en Octubre 27, 2017, 02:02:05 AM
Creo que ya lo he conseguido  :).
Para crear la gravedad según el frame rate es así:
grav = 0.01*60*(global.frame_delta * global.frame_delta);
if (!on_ground)
yVel += grav;

Donde 0.01 es la gravedad, se puede aumentar o disminuir al gusto y 60 es la velocidad de FPS máxima.
Esa formula la encontré de https://www.reddit.com/r/gamemaker/comments/5vvxmr/platformer_gravity_with_delta_time/
Pero falta el impulso y estuve buscando formulas para implementar el salto y así me quedó:
yVel = -(2 * (139 - (global.frame_delta * global.frame_delta)) / room_speed);

Lo encontre en: https://gamedev.stackexchange.com/questions/68559/how-to-obtain-gravity-and-initial-impulse-given-desired-time-to-reach-max-h

Y uso la formula: gravity = -2 * h / (t * t)
Donde gravity en mi caso es yVel, h es la longitud del salto y t es el delta time que sería el tiempo pero como ven relizé una modificación. El único problema es que existe una pequeña variación del salto como de 1 pixel, es decir que cuando está a 60 fps salta la longitud correcta pero cuando va a 30 o 10 fps salta 1 pixel o 2 más arriba pero es mínimo el efecto.

Para implementar es así:
Evento create.
grav = 0;
yVel = 0;
on_ground = 0;


Evento step:(Va después del código de colisiones).
grav = 0.01*60*(global.frame_delta * global.frame_delta);
on_ground = place_meeting(x,y+1,obj_solido);
if (!on_ground)
yVel += grav;
else
if keyboard_check_pressed(vk_up)
yVel = -(2 * (139 - (global.frame_delta * global.frame_delta)) / room_speed);


Es bienvenida cualquier complementación del código, solo quedaría el problema de la pequeña variación pero no es muy notable al fin al cabo pero que más que mejore el código.

Cuando estaba buscando cosas relacionadas con delta time no encontraba mucha información al respecto con la gravedad y el salto o eran temas que no se resolvían, ojalá que con las mejoras que se puedan hacer a este código ayude a resolver esto.
Título: Re:Delta time en salto
Publicado por: Clamud en Octubre 29, 2017, 05:29:05 PM
Creo que sería mejor mantener la gravedad constante y calcular la posición en base al tiempo trascurrido usando la fórmula de movimiento con aceleración constante
[gml]
y = y_prev + vy_prev*t + grav*t*t/2;
[/gml]
Serían necesarias dos variables para guardar el valor de la posición previa y el valor de la velocidad previa.
Título: Re:Delta time en salto
Publicado por: quiero aprender en Octubre 30, 2017, 06:09:13 PM
No estoy muy seguro de como implementarlo.
Buscando información me encontré este vídeo: https://www.youtube.com/watch?v=c4b9lCfSDQM
Donde están las formulas de posición previa:
pos = pos + velocidady * dt
Y velocida previa:
velocidady = velocidady + grav * dt

Entonces en el evento step con las variables ya declaradas en el evento create tengo esto:

grav = 0.2;
pos = yVel;
pos = pos + vsp * global.frame_delta;
vsp = vsp + grav * global.frame_delta;

on_ground = collision_rectangle(bbox_left, bbox_bottom +1 , bbox_right, bbox_bottom +1, obj_block, true, true)

if (!on_ground)
yVel += grav;
else
if keyboard_check(vk_up){
yVel = -(pos + vsp * global.frame_delta + grav*global.frame_delta*global.frame_delta/2); //El código que escribiste
}


Y no me resulto

En que estoy fallando.

Por cierto el código: yVel = -(2 * (139 - (global.frame_delta * global.frame_delta)) / room_speed); solo sirve para cuando el fps sea estable porque cuando baja muy rápido el salto disminuye.
Título: Re:Delta time en salto
Publicado por: quiero aprender en Noviembre 04, 2017, 09:12:14 PM
Creo que ya a quedado resuelto.
En el código de nick agrego esto:
/***************************************************
  Vertical Movement
***************************************************/
if yVel != 0
{
    yVelSub    += yVel * global.frame_delta; /////Aquí agrego el delta time///////////////////////////////////////////////////////////////
    vyNew       = round(yVelSub);
    yVelSub    -= vyNew;
    var ydir    = sign(vyNew)
   
    // Check our direction (up or down)
    if ydir == 0
        var coll = noone
    else if ydir == 1
        var coll = collision_rectangle(bbox_left, bbox_top, bbox_right, bbox_bottom + vyNew, obj_block, true, false)
    else if ydir == -1
        var coll = collision_rectangle(bbox_left, bbox_top + vyNew, bbox_right, bbox_bottom, obj_block, true, false)
    // If there's a collision, move to contact
    if coll
    {
        while (!collision_rectangle(bbox_left, bbox_top + ydir, bbox_right, bbox_bottom + ydir, obj_block, true, false))
        {
            y += ydir;
        }
       
        // Once in contact, set the speeds to 0
        vyNew   = 0
        yVel    = 0
    }
    else // If no contact, move freely
        y += vyNew;
}
}

on_ground = collision_rectangle(bbox_left, bbox_bottom +1 , bbox_right, bbox_bottom +1, obj_block, true, true)

if (yVel < 10){
yVel += grav * global.frame_delta;
}

if on_ground {
    if keyboard_check_pressed(vk_up){
        //yVel = -5.4 * global.frame_delta
        yVel = -jump;
        sprite_index = spr_jump;
    }
}

Las variables grav y jump las declaro en el evento create y ajusto los valores a los que necesito.

Existe una pequeña variación de 2 o 3 pixeles cuando esta a 10 fps a comparación a 60 fps pero por lo menos es estable y nunca se reduce el salto si los fps cambian repentinamente.

Y creo que sería todo.