¿Cómo puedo implementar fácilmente el swing en un juego de plataformas?

9

Estoy desarrollando un juego en el que el jugador puede usar cuerdas para balancearse (al igual que Spiderman o Bionic Commando ) y tengo problemas para implementar este comportamiento. ¿Alguien puede ayudarme a hacer esto? Me refiero a las fórmulas de física, etc. Hasta ahora se me han ocurrido 3 ideas. Uno está usando la primavera, pero consume mucho tiempo y, a veces, está nervioso. Los otros dos están tratando de calcular el siguiente paso (uno a través del cálculo de la energía potencial y otro a través del cálculo del torque) y ambos casi chocan cada vez que el actor intenta balancearse.

Aquí está el código que escribí para calcular el par:

float dx = Runner->getPosition().x - ancher.x; 
float dy = Runner->getPosition().y - ancher.y;
float t0 = atan2(dy,dx); //my current angle
float k = ((dy) *vx - (dx) * vy) / (dx * dx+dy * dy); //previus angular velocity
k -= gravity * cos(t0) *dt; // new angular velocity (gravity is positive)
t0 += k * dt - acc * cos(t0) *dt * dt / 2; // rotate the rope
float dx1 = r0 * cos(t0); // new position (r0 is rope length)
float dy1 = r0 * sin(t0);
vx = (dx1 - dx) / dt; //calculate velocity
vy = (dy1 - dy) / dt;
Ali1S232
fuente
Relevante (al hacer una cuerda): Detección de colisión de cuerda 2D
doppelgreener
@JonathanHobbs, la respuesta en esa pregunta es exactamente cómo estoy tratando de implementar mi cuerda con una excepción, ya que en mi caso no se desea la colisión, configuré cada parte de la cuerda como un sensor para que puedan moverse libremente sin atascarse entre sí.
Ali1S232
¿Qué pasa con el péndulo simple para la cuerda + algunas animaciones que aparecen como cuerdas? No creo que los juegos antiguos como Bionic Commando tuvieran algo más que péndulo.
user712092
@user esa idea de péndulo debería funcionar bien. pero en mi caso, ya sea por el rápido movimiento del jugador o por mi mala implementación, no dio buenos resultados.
Ali1S232
@Gajet intenta hacer un dibujo de depuración hasta que lo hagas bien. Esta línea de péndulo se puede hacer como una caja suficientemente delgada en Box2D para obtener colisiones (¿y tal vez excluirla de la física y moverla a mano?).
user712092

Respuestas:

6

Si desea un swing rígido, por lo que la distancia al punto de rotación es constante, simplemente trate el personaje como un punto en un círculo centrado en el punto de rotación. Dale una velocidad angular unidimensional (a lo largo del círculo). Cada cuadro debe ser la aceleración angular accelerationDueToGravity * cos(angleOfPlayerOnCircle)(con 0 grados apuntando a la derecha).

Si desea que la cuerda se alargue / acorte, puede usar el esquema anterior y solo variar el radio de cada cuadro.

BlueRaja - Danny Pflughoeft
fuente
su respuesta fue mi segundo intento, pero se mueve con mucha más velocidad de la que debería editar mi pregunta y agregar mi código tal vez pueda detectar dónde está el problema.
Ali1S232
3

Después de muchos intentos fui con box2d.

En general, hay dos enfoques para esta simulación o al menos encontré 2:

  1. una es usar algunas formas circulares y conectarlas usando juntas distantes.
  2. y el otro es hacer rectángulos para la cadena en sí y luego unirlos usando juntas giratorias

en cada senario tienes que tener un ancher (que en mi caso era una caja estática). es mejor si baja el peso de las partes de la cuerda (ya sea que use formas circulares o rectangulares), por ejemplo, para tener una física más realista, configuré su densidad en 0.1 y para la caja conectada al final de la cuerda usé la densidad 10.

Otra cosa que debe preocuparse acerca de cómo su segmento de cuerda reacciona entre sí. Solo quería que mi cuerda se moviera libremente en la escena, así que marqué todos los accesorios de la cuerda como sensores. Es posible que necesite un enfoque diferente.

Lo siguiente de lo que debe preocuparse es la cantidad de iteraciones que está pasando a la actualización mundial: para un segmento bajo de cuerda (tal vez 8 como máximo) no hay necesidad de usar un valor de iteración alto tal vez 10/10, que sugirió box2d. es suficiente, pero si aumenta el número de segmento, por ejemplo, probé 30 segmentos, con un número bajo de iteraciones, su cuerda parece aumentar su longitud más de lo que debería, por lo que necesitará quizás 40/40 iteraciones para resolver esas situaciones.

después de algunas pruebas, parece que el cuadro 2d está diseñado para escenas con tamaños de objeto de 0.1m a 10m y el tamaño máximo sugerido para escenas grandes es de unos 50mx50m. Básicamente, necesita escalar su objeto para que coincida con estos parámetros. En mi caso, primero intenté pasar las posiciones de píxeles directamente a box2d, pero parecía que había algunos límites de velocidad que impedían que el mundo se moviera tan rápido como debería, por lo que tuve que escalar mi escena alrededor de 64 veces para obtener los mejores resultados. aunque no me hice la prueba, hay algunos límites en box2d que te impiden usar escenas más grandes. por ejemplo, hay un valor definido en el b2Setting.harchivo #define b2_maxTranslation 2.0f, puede cambiar la configuración de box2d, pero parece que no es recomendable.

Ali1S232
fuente
¿Por qué está mal box2d para ganarme un voto negativo?
Ali1S232
Esto no responde la pregunta. Al menos escribe cómo lo hiciste funcionar usando Box2D.
bummzack
@bummzack: ok, lo agregaré a mi respuesta
Ali1S232
Si acepta esto como su respuesta, su pregunta es defectuosa. La física de la cuerda segmentada es muy diferente de lo que describiste.
AttackingHobo
@attackingHobo: la pregunta era correcta en ese momento, pero cuando transformé mi código a box2d, descubrí que sin mucho esfuerzo puedo implementar física de cuerda segmentada. y no es muy diferente, piense en mi pregunta como solo un segmento de una cuerda segmentada. y casi todas mis soluciones fueron formas de implementar una cuerda estilo círculo sin box2d.
Ali1S232
2

¿Ha considerado reducir la velocidad del movimiento de balanceo en función de qué tan lejos está la cuerda de la plomada (el centro)?

Randolf Richardson
fuente
para los 3 enfoques, la longitud de la cuerda es uno de los parámetros que he usado para calcular la velocidad de balanceo. Pero no puedo garantizar que lo haya usado correctamente. Acabo de hacer algunos cálculos físicos y apliqué su versión resuelta al juego.
Ali1S232
Cuanto más lejos del centro, mayor es la demora antes del próximo movimiento del columpio. También puede multiplicar el valor ABSolute de la demora por algo así como 0.28 (tendrá que experimentar con esto).
Randolf Richardson
No puedo entender lo que intenta decir, cuando estoy calculando el siguiente paso tengo un valor constante para delta_time, y uso todos los parámetros que tengo (como la velocidad anterior, la posición anterior, la longitud de la cuerda, etc.) para calcular nueva velocidad, y luego agregue esta velocidad multiplicada por delta_time a la última posición para generar una nueva posición. Si quiere decir algo más, proporcione todos los detalles en su respuesta.
Ali1S232
1

Cuando el jugador está más allá de la longitud de la cuerda, el jugador será empujado inmediatamente hacia atrás con una fuerza igual a la distancia que la ha pasado. Esto debería funcionar sin sentirse elástico, y debería sentirse intuitivo para el jugador. Sin embargo, es posible que tengas que ajustar tu física para obtener los mejores resultados para tu juego.

Cuando se ata la cuerda. Guardar un maxLengthvalor

Cada actualización, verifique distanceentre player, yattachPoint

Si normalmente distancees menor que la maxLengthactualización, no hay efectos de la cuerda.

Si la distancia es mayor que el maxLength, encuentre el normaldel attachPointal jugador. Obtenga la diferencia entre el distancey maxLength. Agregue al playerVelocity, normalmultiplicado por la diferencia.

Pseudocódigo:

dx = (attachPoint.x - player.x)
dy = (attachPoint.y - player.y)

distance = sqrt(dx*dx+dy*dy);

if (distance > maxDistance)
{
    float dx1 = dx / distance * maxDistance;
    float dy1 = dy / distance * maxDistance;
    v.x += (dx1 - dx) / dt;
    v.y += (dy1 - dy) / dt;
}

playerVel += v * dt;
AttackingHobo
fuente
Entonces, ¿el código que edité en su respuesta (lo siento pero no encontré ningún lugar mejor para agregarlo) es el que está sugiriendo?
Ali1S232
Aprobé la edición, y sí, creo que debería ser así. Aunque utilicé la física de la cuerda antes y utilicé una forma mucho más complicada para hacer lo mismo, por eso no estoy completamente seguro de que este código funcione correctamente, pero creo que debería hacerlo, e incluso si no lo hace, te da 95 % del camino hasta allí.
AttackingHobo
después de algunos intentos, supongo que intentaré box2d para este problema y por cierto tienes que cambiar ese código para que tengas dx = player.x - attachpoint.xy dy = player.y - attachpoint.y.
Ali1S232
1

Si nos fijamos en http://www.cocos2d-iphone.org/archives/1112 hay una implementación de una cuerda con un cuerpo rígido unido al extremo de la cuerda. Utiliza Box2D para el motor de física. Si observa el código fuente, estoy seguro de que puede implementarlo en el idioma que desee.

Además, el enlace anterior a la pregunta de Rope es mío y esta demostración (enlace proporcionado) anterior realmente ayudó.

Joey Green
fuente