Como lidar com a física de plataformas móveis em um jogo de plataformas?

8

Então, depois de algumas horas de pesquisa na internet, ainda não encontrei uma resposta agradável sobre como lidar com plataformas móveis em um jogo de plataforma 2D. Decidi fazer um protótipo simples, onde você interage com 2 plataformas diferentes, uma que se move verticalmente e outra horizontalmente. Eu adoraria alguma ajuda para dissecar e ver o que não está funcionando e como corrigi-los. Enviei o arquivo .fla + .as abaixo, acompanhado de um link para o .swf reproduzível.

O objetivo é fazer com que o Herói interaja com as plataformas como se fossem objetos sólidos nos quais ele possa se apoiar, empurrado ao lado, pular / embaixo etc.

Os problemas com o meu protótipo são estes:

  • Quando você fica na plataforma em movimento horizontal, sem se mover (sem tocar em nenhuma tecla), o Herói se move junto com a plataforma, mas com um pequeno atraso, fazendo com que o herói recue um pouco.

  • Quando você fica na plataforma que se move horizontalmente e pula, você se move junto com a plataforma no ar (alguns jogos preferem tê-lo assim, mas não parece natural e não é desejado aqui). O que pode ser causado pelo herói reter a velocidade no eixo X da plataforma.

  • Quando você pula para o lado inferior na plataforma em movimento vertical, enquanto a plataforma está se movendo para baixo, você afunda por um breve segundo. O herói penetra como se a colisão não existisse por um momento.

  • Quando você pula na plataforma em movimento vertical, a velocidade no eixo Y é mantida; portanto, quando você sai da plataforma, cai em uma velocidade mais alta. Com a velocidade da velocidade retida, + a gravidade adicionada (isso ocorre principalmente porque não consigo descobrir uma maneira de redefinir a velocidade no eixo Y para 0 quando você pousa na plataforma, sem o jogador congelar no ar).

Sou um programador iniciante, por isso tenho certeza de que existem maneiras MELHORES de fazer isso e gostaria de ouvi-las todas. Quaisquer idéias sobre como melhorar o código ou outros métodos nos quais você pode implementar plataformas móveis em um jogo baseado em til são bem-vindas. No final, estou tentando encontrar uma maneira sólida de lidar com plataformas móveis em plataformas 2D.

SWF reproduzível: http://dl.dropbox.com/u/28271061/PlatformerhowtoFLA.html (Mover com as setas, Ir com a tecla X, Executar com a tecla Z)

Arquivo AS do código-fonte: http://dl.dropbox.com/u/28271061/Platformerhowto.as

SourcefileFLA: http://dl.dropbox.com/u/28271061/PlatformerhowtoFLA.fla

Se você preferir apenas ler o código através do Pastie online: http://pastie.org/2266764

Criança
fonte
Relevante (duplicata improvável): Como lidar com plataformas móveis em um jogo de plataforma? .
22411 doppelgreener
Eu li esse tópico, mas como eu não uso os nós de forma alguma, parece que isso não resolveu o problema. O jogo que estou construindo é baseado em blocos, mas as plataformas móveis serão implementadas como acima (movimento livre). Usar nós exigiria uma reescrita do meu mecanismo como um todo, na qual eu já gastei muito tempo. Acho que esperava que alguém olhasse para o código e oferecesse uma solução semelhante à proposta, ou encontrasse uma melhoria no código.
Kid
Você usaria nós depois de implementar essa solução para mover plataformas, mesmo que esse seja o único local em que você as use. Isso resolveria o seu problema de deslizamento.
22411 doppelgreener #
2
"(alguns jogos preferem fazê-lo assim, mas não parece natural e não é desejado aqui)" Como não "parece natural"? Google Inércia e Momentum ...
Riki
11
@ Coração, Natural em termos de jogo, não no mundo físico real. Se você jogar Super Mario Bros ou qualquer um dos clássicos da plataforma, notará que eles NÃO preservam a dinâmica ao pular em plataformas móveis. Isso atrapalha a sensação de estar em pé e interagir com uma plataforma móvel.
26611 Kid

Respostas:

17

Vamos separar seu problema em problemas distintos ...

Uma palavra sobre a qualidade do código

Atualmente, seu código tem suas plataformas controlando diretamente a velocidade do seu jogador e até a constante de gravidade do mundo . É hacky e processual quando deveria ser orientado a objetos. Quando você começar a expandir esse jogo, as coisas ficarão feias rapidamente .

Você precisa refatorar seu código. Implemente uma classe de jogador, uma classe de plataforma e uma classe de andar. Separe suas preocupações: peça ao jogador que interprete os controles do teclado e controle como ele corre e salta, e faça com que as plataformas alterem seu momento conforme necessário (adicionando sua própria velocidade à velocidade já determinada do jogador, quando necessário).

Peça ao seu jogador que determine onde está em relação a um objeto do tipo piso (plataformas e pisos teriam um BodyType = BodyTypes.Floor, ou algo assim) e determine por si próprio onde está em relação ao objeto, como deve reagir e se está caindo ou não. no chão.

Isso pode merecer um tópico separado, pois é uma questão bastante separada de tudo que você mencionou. No entanto, você precisará fazer isso em algum momento.

Inércia horizontal / vertical ao sair de uma plataforma

Para resolver seus problemas de velocidade vertical e horizontal, observe duas coisas:

  • Em relação à velocidade horizontal: Seu código define a velocidade horizontal como 0 quando o jogador atinge o chão (na linha 200 da Pastie) ou em uma plataforma.
  • Em relação à velocidade vertical: Seu aparelho tem uma aceleração constante de queda. Quando ele sai da plataforma vertical, essa aceleração decrescente continua aumentando seu movimento já descendente.

Seu jogador está simplesmente sofrendo de inércia : o momento dele é mantido até que algo o interrompa.

Solução: Ambos os problemas seriam resolvidos pela solução da jSepia para Como lidar com plataformas móveis em um jogo de plataforma? pois separaria completamente o processo de movimentação do jogador de como as plataformas o movem. Você simplesmente não cairia mais rápido ao sair de uma plataforma vertical e não preservaria seu momento horizontal saltando de uma plataforma horizontal, porque as plataformas não afetarão mais o vx e vy do seu jogador .

Nota: Você pode ter alguma dificuldade em implementar a solução do jSepia antes que seu código seja refatorado.

Deslizando de um lado para o outro pela plataforma horizontal

Seu jogador não é movido horizontalmente tão rápido quanto a plataforma se move. Não é óbvio para mim o porquê. Esse problema provavelmente também seria resolvido com a implementação da solução da jSepia e a refatoração correta do seu código (o último simplesmente tornaria a causa óbvia).

Detecção de colisão: sobreposição com a plataforma vertical

Veja a linha 381 do Pastie: a cada passo, é redefinido o vy do jogador para 0, desde que o jogador colidir com a parte inferior da plataforma vertical. Na etapa seguinte, vy é aumentado pela aceleração da gravidade e, em seguida, o jogador é movido (e depois redefinido para 0 novamente).

Isso significa que, enquanto o seu jogador estiver colidindo com o fundo da plataforma, ele estará se movendo para baixo a uma velocidade constante (a constante da gravidade). A plataforma vertical é mais rápida que isso, por isso se sobrepõe. Se a plataforma vertical se movesse por uma distância maior, ela deslizaria através dele até o jogador ser registrado como estando na plataforma.

Solução: não redefina o vy do jogador para 0. Basta definir o vy do jogador para a velocidade vertical da plataforma ( se a plataforma estiver viajando para baixo ). Seu player estará se afastando da plataforma vertical pelo menos tão rápido quanto a plataforma e acelerando para longe dela.

doppelgreener
fonte
Excelente! Em primeiro lugar, obrigado pela solução para pular e penetrar na plataforma vertical (funciona!). E segundo, você está certo, o código é terrível nesse estado. Embora este não seja o jogo em si, este é um protótipo rápido feito para experimentar e entender melhor as plataformas móveis. No entanto, se eu quiser traduzir isso para o código real dos jogos, devo manter um código mais estruturado e orientado a objetos. Isso suavizará a transferência. Agora, com relação à solução jSpeias, acho que entendi o conceito de árvore de nós, mas não sei como implementá-lo corretamente.
26711 Kid
Meu primeiro pensamento é criar valores booleanos que descrevam o estado dos players, como: "onFloor", "onPlatform", "onGround", "falling", "jumping", etc. E, em seguida, execute uma instrução if no evento enterFrame que verifica o estado atual e altera as propriedades dos Jogadores de acordo (?) Por exemplo: if (Hero.onPlatform == true) {Player.x = platform.x (relativo ao player global x);}. Algo dessa maneira.
26711 Kid
Estou trabalhando nisso enquanto falamos, mas, ao mesmo tempo, separo o código em diferentes classes, como você sugeriu, o que também é um pouco confuso (a comunicação entre as classes de plataforma / colisão / jogador é incompreensível).
Kid
@Kid: Playerpossui um método GetPositione variáveis ​​internas parent(para o nó pai) e position(para sua posição em relação ao pai). Player.GetPosition()retorna position + parent.GetPosition(). Seu pai faz a mesma coisa até chegar à raiz da árvore - o nó do mundo. Quando o seu jogador se move, você lida apenas com a positionvariável privada . Seu jogador é sorteado na tela do jogo de acordo com GetPosition()o valor. Vou deixar você descobrir como fazer a transição entre nós. ;)
doppelgreener
Ter uma classe jogador saber como modificar a sua própria velocidade, claro, não é a separação defesa dos interesses
Andy Ray