En el siguiente video hay 2 pruebas.
En la 1era, cuando el personaje camina tiene 2 estados, y en uno es más ancho que en el otro, estira los pies hacia adelante. Eso hace que el barril sea empujado muchas veces en un mismo contacto, lo cual le da demasiada velocidad, está mal. El error ocurre porque en este caso el contacto se produjo cuando el personaje era menos ancho, luego se ensancha y entonces el programa sigue detectando que está tocando el barril, hasta que por fin se aleja suficiente.
En la 2nda prueba, el personaje no cambia al caminar, siempre tiene el mismo ancho, el movimiento del barril está bien, pero el personaje debería cambiar al caminar.
https://youtu.be/eWPQZnodI1U
¿Cómo logro que quede bien?
Puedo poner un ancho único. Que, sin importar el ancho del personaje, el contacto se produzca siempre a la misma distancia. Pero no me gusta eso.
Puedo poner que al ocurrir el hecho una variable cambie durante un tiempo, en el cual el barril no podrá ser empujado de nuevo. Tampoco me parece buena idea.
Busco una solución digamos lógica o realista. Si alguien va caminando, cuando adelanta la pierna tiene más ancho, entonces empuja algo que está más lejos. Si justo lo empuja cuando tiene las 2 piernas juntas, es como si lo empujara varias veces, pero ¿con menos fuerza? No sé, e intentando encontrar fallas cambié varias cosas así que algunas puede que hayan quedado mal.
El código en resumen es:
1- Cuando el personaje camina, se calcula su distancia con respecto al barril:
DistanciaPlayerBarril = ValorAbsoluto(PlayerX-BarrilX);
Las coordenadas que se consideran son los centros de los objetos, o sea, distancia entre el centro del personaje y el centro del barril.
2- Se calcula esto:
MinDistanciaSinChoque = PlayerAncho/2+14+0.2;
O sea, el ancho del personaje/2 + el ancho del barril/2 (da 14) y 0.2 que es lo que el personaje se moverá.
Es la mínima distancia a la que están sin chocar. Como el personaje se moverá 0.2, se agrega eso.
3- Se compara la distancia con eso, para detectar si el personaje tocará el barril o no:
if (DistanciaPlayerBarril<MinDistanciaSinChoque) {
4- Supongamos que habrá contacto, ya que es lo relevante aquí. En tal caso tengo esto:
// Determinar movimientos:
// MinDistanciaSinChoque -> mov 0.2, empuje 0.
// 0 -> mov 0, empuje 0.2.
MovimientoDelPers = DistanciaPlayerBarril*0.2/MinDistanciaSinChoque;
...la idea es que normalmente el personaje se mueva 0.2, pero si va a tocar el barril se mueva menos, y lo que reste se aplique a la velocidad del barril, en el siguiente paso del programa.
Entre más cerca estén, menos se moverá el personaje.
5- Aquí puse que el barril aumente siempre la misma velocidad independientemente de cuánto sea MovimientoDelPers, porque eso me daba problemas. Deberá mejorarse:
BarrilSpeed = BarrilSpeed+0.3;
...antes creo que tenía esto:
BarrilSpeed = BarrilSpeed+0.2-MovimientoDelPers;
Como el barril se detiene si su velocidad es muy poca, eso me daba problemas, creo que era así.
Creo que eso es todo. Luego se reduce la velocidad del barril debido a rozamiento, pero eso creo que ya está bien, ya pregunté aquí.
En Mario Bros, cuando Mario toca un caparazón de tortuga o similar, ésta adquiere más velocidad que la que él puede tener y además no tiene rozamiento, por eso en ese juego no ocurren estos problemas xP