Como posso implementar facilmente o swinging em um jogo de plataformas?

9

Estou desenvolvendo um jogo no qual o jogador pode usar cordas para balançar (exatamente como o Spiderman ou o Bionic Commando ) e estou tendo problemas para implementar esse comportamento. Alguém pode me ajudar a fazer isso, quero dizer fórmulas de física e etc. Até agora eu tenho três idéias. Um deles usa a primavera, mas consome muito tempo e, às vezes, é instável. Os outros dois estão tentando calcular o próximo passo (um através do cálculo da energia potencial e outro através do cálculo do torque) e os dois quase batem sempre que o ator está tentando balançar.

Aqui está o código que escrevi para calcular o torque:

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
fonte
Relevante (ao fazer uma corda): Detecção de colisão em corda 2D
doppelgreener
@JonathanHobbs, a resposta nessa pergunta é exatamente como estou tentando implementar minha corda com uma exceção, uma vez que a colisão é indesejável no meu caso. Defino cada parte da corda como um sensor para que eles possam se mover livremente sem ficarem presos um no outro.
Ali1S232
Que tal um pêndulo simples para corda + algumas animações que parecem com corda? Não acredito que jogos antigos como o Bionic Commando tivessem algo mais que pêndulo.
usar o seguinte comando
@ usuário que a idéia do pêndulo deve funcionar bem. mas no meu caso, devido ao movimento rápido do jogador ou à minha má implementação, não deu bons resultados.
Ali1S232
@ Gajet tenta fazer algum desenho de depuração até você acertar? Essa linha de pêndulo pode ser feita como uma caixa suficientemente fina no Box2D para obter colisões (e talvez excluí-la da física e mover-se à mão?).
user712092

Respostas:

6

Se você deseja um balanço rígido, para que a distância até o ponto de rotação seja constante, trate o personagem como um ponto em um círculo centrado no ponto de rotação. Dê a ele uma velocidade angular unidimensional (ao longo do círculo). Para cada quadro a aceleração angular deve estar accelerationDueToGravity * cos(angleOfPlayerOnCircle)(com 0 graus apontando para a direita).

Se você deseja que a corda fique mais longa / mais curta, você pode usar o esquema acima e apenas variar o raio de cada quadro.

BlueRaja - Danny Pflughoeft
fonte
você respondeu que foi minha segunda tentativa, mas ela se move com muito mais velocidade do que deveria. Eu devo editar minha pergunta e adicionar meu código. Talvez você possa identificar onde está o problema.
Ali1S232 31/05
3

depois de muitas tentativas, fui com o box2d.

geralmente existem duas abordagens para esta simulação ou pelo menos eu encontrei 2:

  1. uma é usar algumas formas de círculo e conectá-las usando juntas distantes.
  2. e o outro é retângulos para a própria corrente e, em seguida, prenda-os usando juntas de revolução

em cada senario você precisa ter um ancher (que no meu caso era uma caixa estática). é melhor se você diminuir o peso das peças do cabo (use formas circulares ou retangulares), por exemplo, para ter uma física mais realista, defino sua densidade como 0,1 e, para a caixa conectada no final da corda, usei a densidade 10.

Outra coisa é que você precisa se preocupar com a forma como seu segmento de corda reage um ao outro. Eu só queria que minha corda se movesse livremente na cena, então marquei todos os acessórios como sensores. você pode precisar de uma abordagem diferente.

a próxima coisa com a qual você deve se preocupar é o número de iterações que você está executando na atualização mundial: para um segmento baixo de corda (talvez 8 no máximo), não há necessidade de usar um valor de iteração alto, talvez 10/10, o que o próprio box2d sugeriu é suficiente, mas se você aumentar o número de segmentos, por exemplo, tentei 30 segmentos, com baixo número de iterações, sua corda parece aumentar seu comprimento mais do que deveria, portanto, talvez você precise de novas iterações 40/40 para resolver essas situações.

após alguns testes, parece que a caixa 2d foi projetada para cenas com tamanhos de objeto de 0,1m a 10m e o tamanho máximo sugerido para cenas grandes é algo em torno de 50mx50m. tão básico que você precisa dimensionar seu objeto para baixo para corresponder a esses parâmetros. no meu caso, tentei passar as posições de pixel diretamente para o box2d, mas parecia que havia alguns limites de velocidade que impediam o mundo de se mover o mais rápido que deveria, então tive que escalar minha cena em torno de 64 vezes para obter os melhores resultados. embora eu não tenha me testado, existem alguns limites no box2d que o impedem de usar cenas maiores. por exemplo, há um valor definido no b2Setting.harquivo. #define b2_maxTranslation 2.0fVocê pode alterar as configurações do box2d, mas isso não é recomendado.

Ali1S232
fonte
por que está errado com o box2d para ganhar um voto negativo?
Ali1S232
Isso não responde à pergunta. Pelo menos escreva como você o fez usando o Box2D.
bummzack
@bummzack: ok eu vou acrescentar que a minha resposta
Ali1S232
Se você aceitar isso como sua resposta, sua pergunta será falha. A física de cordas segmentadas é muito diferente do que você descreveu.
AttackingHobo
@attackingHobo: o quesiton estava correto naquele momento, mas quando eu mudei meu código para box2d, descobri que, sem muito esforço, posso implementar física de cordas segmentada. e não é muito diferente, pense na minha pergunta como apenas um segmento de uma corda segmentada. e quase todas as minhas soluções foram formas de implementar uma corda circular sem o box2d.
Ali1S232
2

Você já pensou em diminuir a velocidade do movimento de giro com base na distância que a corda está da linha de prumo (no centro)?

Randolf Richardson
fonte
para todas as três abordagens, o comprimento da corda é um dos parâmetros que eu usei para calcular a velocidade do balanço. Mas não posso garantir que o usei corretamente. Acabei de fazer alguns cálculos físicos e apliquei a versão resolvida no jogo.
Ali1S232 31/05
Quanto mais distante do centro, maior o atraso antes do próximo movimento do balanço da corda. Você também pode multiplicar o valor ABSolute do atraso por algo como 0,28 (você precisará experimentar isso).
Randolf Richardson 31/05
Não consigo entender o que você está tentando dizer, quando estou calculando o próximo passo, tenho algum valor constante para delta_time e uso todos os parâmetros que tenho (como velocidade do previus, posição do previes, comprimento da corda, etc.) para calcular nova velocidade e adicione essa velocidade multiplicada por delta_time à última posição para gerar nova posição. se você quer dizer algo mais, forneça detalhes completos em sua resposta.
Ali1S232 31/05
1

Quando o jogador estiver além do comprimento da corda, ele será imediatamente empurrado para trás com uma força igual à distância pela qual ele passou. Isso deve funcionar sem parecer elástico e deve ser intuitivo para o jogador. Você pode ter que ajustar sua física para obter os melhores resultados para o seu jogo.

Quando a corda está presa. Salve um maxLengthvalor.

A cada atualização, verifique distanceentre playerasattachPoint

Se o valor distancefor menor que a maxLengthatualização normalmente, nenhum efeito da corda.

Se a distância for maior que a maxLength, encontre o normalde attachPointpara o jogador. Obtenha a diferença entre o distancee maxLength. Adicionar à playerVelocity, normalmultiplicado pela diferença.

Pseudo-có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
fonte
então o código que editei na sua resposta (desculpe, mas não achei melhor lugar para adicioná-lo) o que você está sugerindo?
#
Eu aprovei a edição e, sim, acho que deveria ser. Embora eu tenha usado a física das cordas antes e usado uma maneira muito mais complicada de fazer a mesma coisa, por isso não tenho certeza absoluta de que esse código funcione corretamente, mas acho que deveria, e mesmo que não, ele o deixa % do caminho até lá.
AttackingHobo
depois de algumas tentativas, acho que vou tentar o box2d para esse problema e, a propósito, você precisará alterar esse código para que você tenha dx = player.x - attachpoint.xe dy = player.y - attachpoint.y.
#
1

Se você olhar para http://www.cocos2d-iphone.org/archives/1112, há uma implementação de uma corda com um corpo rígido preso ao final da corda. Ele usa o Box2D para o mecanismo de física. Se você olhar o código-fonte, tenho certeza de que pode implementá-lo em qualquer idioma que desejar.

Além disso, o link acima para a pergunta Rope é meu e esta demonstração (link fornecido) acima realmente ajudou.

Joey Green
fonte