Como alguém determinaria a posição de um participante de um jogo de corrida?

9

Agora, para constar, atualmente não estou implementando nenhum jogo de corrida, mas esse problema me veio à mente e agora estou curioso.

Então, como descobrir qual participante de uma corrida é atualmente o primeiro? Não pode ser algo trivial como apenas classificar por distância até a linha de chegada, porque isso seria altamente impreciso na maioria dos cursos. Eu pensei em fazer algo como separar a rota em segmentos retos, cada um dos quais com um vetor de direção. O jogo então verifica quando alguém ultrapassa alguém, projetando suas posições nesse vetor e verificando qual deles está à frente. Se a posição mudasse, o jogo aumentaria / diminuiria adequadamente. Mas isso parece um pouco complicado demais.

Alguém conhece algum método estabelecido ou tem alguma experiência na implementação de alguns?

Marc Müller
fonte

Respostas:

12

Shawn Hargreaves descreve como o MotoGP usou um sistema especial de posição relativa à pista . Ignorando a posição vertical y, as coordenadas cartesianas x / z são convertidas em um sistema relativo a trilhas. Isso teve muitos benefícios para cálculos envolvendo as posições relativas dos participantes de um jogo de corrida (por exemplo, para a IA):

Uma simplificação comum é recolher o 3D em 2D. Embora a renderização e a física possam ser verdadeiramente 3D, a lógica da tomada de decisão não precisa tratar os três eixos igualmente. As trilhas de MotoGP têm poucas colinas, então nossa IA foi capaz de ignorar o componente y.

Em seguida, passamos de coordenadas cartesianas x / z para um sistema relativo a trilhas. As posições foram representadas por um par de valores:

int distance = a que distância da pista é armazenada no formato de ponto fixo 16.16

  • 0 = linha de partida
  • 0x8000 = meio caminho andado
  • 0x10000 = volta ao início
  • 0x1C000 = três quartos da segunda volta

float cross = a que distância lateral da pista 0 = na linha central

  • -1 = borda esquerda da superfície de corrida
  • 1 = borda direita da superfície de corrida

Para converter entre isso e as coordenadas cartesianas usadas por nosso código físico e de renderização, armazenamos uma lista de segmentos que definem a forma da superfície de corrida: struct TrackSegment {Vector CenterPoint; float DistanceToLeftEdge; flutuar DistanceToRightEdge; }

Criamos várias centenas dessas estruturas, espaçadas uniformemente ao redor da pista, classificando as curvas de Bezier a partir das quais as faixas foram originalmente criadas. Isso nos deu informações suficientes para escrever as funções necessárias de conversão de coordenadas.

Com as coordenadas relativas à faixa, muitos cálculos úteis se tornam trivialmente simples:

if (abs(cross) > 1)
    // You are off the track and should steer back toward the center line


if (this.distance > other.distance)
    // You are ahead of the other player (even though you may be
    // physically behind in 3D space if you have lapped them)


short difference = (short)(this.distance - other.distance);

if (abs(difference) < threshold)
    // These two bikes are physically close together,
    // so we should run obstacle avoidance checks

Devido ao formato de dados do ponto fixo, converter o contador de distância de 32 a 16 bits era uma maneira fácil de descartar o número da volta, para que pudéssemos escolher quais cálculos se importariam se duas bicicletas estivessem em voltas diferentes, em vez de querer saber se elas estavam perto no espaço físico. Graças à magia do elogio de dois, tratar a diferença como 16 bits assinada oferece a menor distância, independentemente da bicicleta à frente (lembre-se de que em um sistema aritmético modular, como uma pista de corrida em loop, existem duas distâncias possíveis, como você pode medir em qualquer direção ao redor da pista). Isso funciona mesmo quando as duas bicicletas estão em lados opostos da linha de partida, uma situação que exigiria lógica de caso especial propensa a erros na maioria dos outros sistemas de coordenadas.

Achatar e endireitar esta área de jogo virtual facilitou o raciocínio sobre coisas como "estou na linha de corrida?" ou "Estou chegando rápido atrás dessa outra bicicleta: tenho mais espaço para passá-las à esquerda ou à direita?" o que seria difícil de implementar em um espaço mundial em 3D completo. Uma vez que decidimos passar à esquerda, converteríamos a coordenada relativa à trilha resultante de volta ao espaço do mundo, momento em que a curvatura da trilha é levada em consideração, mostrando como devemos orientar para alcançar nosso objetivo escolhido.

Leftium
fonte
Muito agradável! Muito obrigado. Também obrigado por adicionar as tags apropriadas. Não consegui fazê-lo devido à falta de reputação. Felicidades.
Marc Müller
3

Eu acho que usaria o fato de que a estrada geralmente é construída usando splines; portanto, cada beira da estrada tem uma posição correspondente, e usando isso você pode determinar (aproximadamente ou granularidade se subdividir mais) qual é a corrente A posição estriada de cada carro é e, portanto, quem está na liderança. Então, mais ou menos da maneira que você sugere, apenas usando o spline.

Kaj
fonte
3

Você respondeu mais ou menos a sua própria pergunta, eu acho. Divida a pista em segmentos, rastreie em qual segmento cada carro está e projete os carros em uma linha no meio do segmento apropriado (matematicamente, é um simples produto escalar, portanto, não é nada complicado). É muito simples atribuir a cada carro uma "distância" que você pode classificar por posição.

Os segmentos oferecem um benefício adicional - você pode garantir que os carros não cortem os cantos (ou geralmente atalhos), retrocedam ou outros truques.

JasonD
fonte