Movimento suave em um jogo baseado em peças

8

Como podemos fazer nosso personagem se mover suavemente através de peças? Ele move ladrilhos por ladrilhos, mas isso parece pouco profissional. Além disso, quando você mantém as teclas de seta pressionadas, ele fecha a tela. Como podemos impedir que isso aconteça?

leo882
fonte
Você está usando números inteiros para o movimento do jogador. Tente usar carros alegóricos.
Mokosha #
11
É melhor se você reduzir seu código ao mínimo necessário para demonstrar / comunicar seu problema / pergunta. Além disso, você pode estar interessado nesta questão .
Kevintodisco #
11
Eu removi as partes desnecessárias da sua pergunta. É melhor ir direto ao ponto e não adicionar código adicional ou outro fluff.
MichaelHouse

Respostas:

6

O movimento suave pode ser alcançado de várias maneiras. E isso realmente depende do tipo de movimento que você deseja permitir.

  • Movimento ainda restrito a ladrilhos. Esse tipo é o mais fácil para realizar ações como detecção de colisão e outras verificações de movimento. Para esse tipo de movimento, você simplesmente interpolará a posição ao longo do tempo enquanto faz a transição entre blocos. Pode ser tão simples quanto adicionar algo como o seguinte ao loop de atualização.

Pseudo-código:

 if(GetDistance(position, targetposition) > minDistance) {
     position = MoveTowards(position, targetposition, deltatime);
 }

Onde MoveTowardsapenas assume a posição atual e adiciona uma parte da distância entre ela e a posição de destino.

  • O movimento não se restringe a peças. Isso fica muito mais complicado de implementar. Essencialmente, com esse método, você apenas armazena a posição e atualiza-a via velocidade. Ou seja, mudança de posição ao longo do tempo.

Manter as teclas de seta pressionadas para mover os caracteres também pode ser implementado de algumas maneiras diferentes. Provavelmente, o que você está fazendo é algo como:

if(keydown(left))
   tilePosition.X--;

Isso realmente faria com que o personagem passasse pela tela. Como você atualizaria a posição várias vezes por segundo. Uma maneira um pouco melhor de implementar isso seria adicionar um atraso. Algo como

if(keydown(left)) {
    if(leftKeyHeldTimer > movementDelay) {
        tilePosition.X--;
        leftKeyHeldTimer = 0;
    } else {
        leftKeyHeldTimer+= deltaTime;
    }
}

Isso adicionará um temporizador de atraso e somente atualizará a posição do bloco quando o movementDelayvalor for atingido.

MichaelHouse
fonte
0

Eu consigo identificar dois problemas. O primeiro está relacionado ao movimento suave e o segundo está relacionado ao personagem saindo da tela.

Para criar um movimento suave, você pode usar uma técnica chamada Interpolação Linear ou (LERP) para suavizar o movimento. Basicamente, como ele funciona é entre o ponto inicial e o ponto final, você calcula um conjunto de distâncias cada vez menores para simular movimentos suaves e diminuir a velocidade quando o ponto final é quase atingido.

O exemplo mais simples dessa função seria:

//point1 is the current position, will be starting position on first call
//point2 is the target position
//epsilon is the % of the distance between current and target you want
//to cover per game physics loop (a fixed realworld time based loop).
//The smaller the % the "smoother" the motion.

float lerp(float point1, float point2, float epsilon)
{
    return point1 + epsilon * (point2 - point1);
}

À medida que o personagem se aproxima do ponto 2, ele diminui gradualmente. Observe que eles nunca tocam o ponto 2, mas ficam infinitamente próximos. Você precisaria corrigir isso e se o jogador estiver a uma distância infinitamente pequena do ponto 2, podemos considerar o jogador no ponto 2.

A segunda questão que você mencionou está relacionada ao seu personagem voando para fora da tela. Isso é resultado da leitura de cada entrada de atualização de loop do jogo combinada com o movimento instantâneo entre as peças.

Idealmente para resolver isso, em seu código você precisa decidir

  1. Quanto tempo no mundo real levaria para o personagem passar do ponto 1 para o ponto 2.
  2. Defina seu Lerp para executar entre o ponto 1 e dois durante essa duração
  3. Leia a entrada novamente quando o ponto 2 for alcançado para decidir para onde ir
Ang Li
fonte