Hola a todos. Soy nuevo. Estoy empezando con Game Maker y mire este tutorial de movimiento para un juego de plataformas: https://www.youtube.com/watch?v=izNXbMdu348
Basicamente el codigo es el siguiente:
CREATE EVENT:
hsp = 0
vsp = 0
grv = 0.3
walkspeed = 4
//Get Player Input //
key_left = keyboard_check(vk_left);
key_right = keyboard_check(vk_right); 
//Calculate Movement //
var move = key_right - key_left; 
hsp = move * walksp; 
vsp = vsp + grv; 
//Horizontal collision //
if (place_meeting(x+hsp,y,oWall))
{     
while (!place_meeting(x+sign(hsp),y,oWall)) 
{      x = x + sign(hsp);

hsp = 0;
}
x = x + hsp; 
//Vertical Collision //
if (place_meeting(x,y+vsp,oWall))
{   while (!place_meeting(x,y+sign(vsp),oWall))
{    y = y + sign(vsp);  }
vsp = 0;
}
y = y + vsp;

----------------------------------------------------------------------------------------------------------------------------------------------------
Bueno, entendi basicamente todo menos una sola parte en la parte de "Colision vertical"
El codigo dice que la gravedad es igual a 0.3 y que la velocidad vertical es 0.
Despues dice que la velocidad vertical es la velocidad vertical mas la gravedad. Basicamente la velocidad vertical siempre
va a ser 0 + 0.3 que da siempre 0.3
Bueno, hasta ahi todo bien. Lo que no entiendo es lo siguiente:
En la parte de colision vertical primero se fija a ver si hay una pared 0.3 pixeles debajos nuestro y despues de eso tiene un while que se fija
a ver si NO hay una pared 1 pixel debajo nuestro. Esa es la parte que no entiendo. Osea porque fijarse si NO hay una pared 1 pixel debajo nuestro si ya sabemos que absolutamente si hay una pared debajo nuestro, sino la hubiera el evento de if seria falso y no estariamos checkeando eso. Es muy confuso. Despues de eso dice "si no hay una pared 1 pixel debajo nuestro, entonces move el jugador 1 pixel hacia abajo" Pero eso es muy confuso porque ya sabemos que si hay una pared debajo nuestro y encima va a mover el jugador 1 pixel mas abajo. En teoria eso deberia hacer que el jugador se quede atascado en el suelo. Pero la realidad es que el codigo FUNCIONA PERFECTAMENTE. Funciona bien, no tiene ningun problema y la gravedad funciona bien PERO LO QUE YO QUIERO ES ENTENDER POR QUE FUNCIONA. REALMENTE NO ENTIENDO PORQUE. Quiero entenderlo para aprender y no solamente copiar codigo sin entender nada ¿Que es lo que no estoy entendiendo? ¿Porque ese codigo funciona tan bien? Espero haber sido claro.

#1 Abril 18, 2020, 06:58:56 PM Ultima modificación: Abril 18, 2020, 07:04:01 PM por dixon
Hola, gusto en saludarles.

Código a analizar:


if (place_meeting(x,y+vsp,oWall))
{   while (!place_meeting(x,y+sign(vsp),oWall))
{    y = y + sign(vsp);  }
vsp = 0;
}



if(place_meeting(x,y+vsp,owall))
{
De existir un obejto llamado "owall" a una distancia de vsp entonces:



while (!place_meeting(x,y+sign(vsp),owall))
mientras no exista el objeto "owall" a una distancia de un pixel



{
y=y+sign(vsp)
}
Sumarle a su posición Y un pixel



vsp=0
La velocidad debe volverse cero


}



En otras palabras:
Si el player se encuentra verticalmente cerca de un objeto "owall" acércalo a él y vuelve su velocidad cero.

Otras palabras
Si el player tiene un objeto cerca de sus pies, acércalo a él hasta encontrar el objeto.

En otras palabras:
Si el player está a punto de tocar el suelo, que se pegue al suelo y se vuelva la velocidad cero.

Este código al parecer funciona también con las colisiones con el techo, porque está tomando el signo de la vspeed. Por lo tanto está diciendo
Si el objeto player está saltando y sobre su cabeza se encuentra un techo entonces pégalo al techo pero detén la velocidad.

Este código se esta usando para corregir las colisiones verticales y evitar dos cosas:
1. Evitar que el player traspase los objetos "owall"
2. Evitar que la colisión vertical con los objetos "owall" se vea mal.

El código está correcto y funciona como un imán magnético. Donde el objeto owall atrae con su magnetismo al player, pero esto no quiere decir que se va a quedar pegado sino que antes que el player colisione con el objeto owall se va a pegar a el y su velocidad será cero.

1. El código no hace nada si la distancia es superior a la vsp: Si dos objetos de distinta polaridad están muy separados no se percibirá a simple vista su atracción magnética.
2. El código funciona solo cuando el player está cerca del objeto owall: Si dos objetos magnéticos con carga distinta están cerca entonces existirá atracción magnética.

¿Por qué el código es así?
Cuando colisionamos con un objeto solo necesitamos decirle al player que su velocidad sea cero pero esto no se ve bien porque queda una distancia entre el suelo y el player, entonces surge este código para corregir la distancia.

Código sin corrección de distancia: El player queda en el aire o traspasa la owall




if (place_meeting(x,y+vsp,oWall))
{   
vsp = 0;
}

Código corregido: el player no traspasa la owall


if (place_meeting(x,y+vsp,oWall))
{   while (!place_meeting(x,y+sign(vsp),oWall))
{    y = y + sign(vsp);  }
vsp = 0;
}

¿Porqué vsp y sign(vsp)?
Porque vsp normalmente es mayor que sign(vsp).  La vsp es la velocidad de movimiento y también es la distancia que se recorrerá en el próximo paso. Si el objeto player está saltando la vsp será negativa y el sign(vsp) será -1. Si el player está cayendo entonces la vsp será positiva y el sign(vsp) será 1.

¿Podría presentar fallas este código?
Sí, pero solo cuando la vsp es muy alta. En ese caso el objeto player puede que  no detecte el objeto owall y lo traspase. Para evitar eso se usa otro código.

Todavía hay mucho que explicar de este código pero por ahora solo dejo las imágenes:












Si Dios quiere; Limpiaré la oficina, puliré el piso y les serviré café a todos, luego, me enseñarán a programar e iré a comprarles más café.

Cita de: dixon en Abril 18, 2020, 06:58:56 PM
Hola, gusto en saludarles.

Código a analizar:


if (place_meeting(x,y+vsp,oWall))
{   while (!place_meeting(x,y+sign(vsp),oWall))
{    y = y + sign(vsp);  }
vsp = 0;
}



if(place_meeting(x,y+vsp,owall))
{
De existir un obejto llamado "owall" a una distancia de vsp entonces:



while (!place_meeting(x,y+sign(vsp),owall))
mientras no exista el objeto "owall" a una distancia de un pixel



{
y=y+sign(vsp)
}
Sumarle a su posición Y un pixel



vsp=0
La velocidad debe volverse cero


}



En otras palabras:
Si el player se encuentra verticalmente cerca de un objeto "owall" acércalo a él y vuelve su velocidad cero.

Otras palabras
Si el player tiene un objeto cerca de sus pies, acércalo a él hasta encontrar el objeto.

En otras palabras:
Si el player está a punto de tocar el suelo, que se pegue al suelo y se vuelva la velocidad cero.

Este código al parecer funciona también con las colisiones con el techo, porque está tomando el signo de la vspeed. Por lo tanto está diciendo
Si el objeto player está saltando y sobre su cabeza se encuentra un techo entonces pégalo al techo pero detén la velocidad.

Este código se esta usando para corregir las colisiones verticales y evitar dos cosas:
1. Evitar que el player traspase los objetos "owall"
2. Evitar que la colisión vertical con los objetos "owall" se vea mal.

El código está correcto y funciona como un imán magnético. Donde el objeto owall atrae con su magnetismo al player, pero esto no quiere decir que se va a quedar pegado sino que antes que el player colisione con el objeto owall se va a pegar a el y su velocidad será cero.

1. El código no hace nada si la distancia es superior a la vsp: Si dos objetos de distinta polaridad están muy separados no se percibirá a simple vista su atracción magnética.
2. El código funciona solo cuando el player está cerca del objeto owall: Si dos objetos magnéticos con carga distinta están cerca entonces existirá atracción magnética.

¿Por qué el código es así?
Cuando colisionamos con un objeto solo necesitamos decirle al player que su velocidad sea cero pero esto no se ve bien porque queda una distancia entre el suelo y el player, entonces surge este código para corregir la distancia.

Código sin corrección de distancia: El player queda en el aire o traspasa la owall




if (place_meeting(x,y+vsp,oWall))
{   
vsp = 0;
}

Código corregido: el player no traspasa la owall


if (place_meeting(x,y+vsp,oWall))
{   while (!place_meeting(x,y+sign(vsp),oWall))
{    y = y + sign(vsp);  }
vsp = 0;
}

¿Porqué vsp y sign(vsp)?
Porque vsp normalmente es mayor que sign(vsp).  La vsp es la velocidad de movimiento y también es la distancia que se recorrerá en el próximo paso. Si el objeto player está saltando la vsp será negativa y el sign(vsp) será -1. Si el player está cayendo entonces la vsp será positiva y el sign(vsp) será 1.

¿Podría presentar fallas este código?
Sí, pero solo cuando la vsp es muy alta. En ese caso el objeto player puede que  no detecte el objeto owall y lo traspase. Para evitar eso se usa otro código.

Todavía hay mucho que explicar de este código pero por ahora solo dejo las imágenes:








Hola :D ¡Muchisimas gracias! Se nota que te tomaste el tiempo de hacer una respuesta clarisima y te pasaste la verdad, muy buena tu respuesta ¿Te podria hablar por privado para pedirte ayuda con un proyecto?