Estou criando um jogo webgl gratuito “Piratas” com combates e puzzles e queria criar alguma diversidade de jogabilidade adicionando níveis de corrida, com dois modos dependendo do nível, o final clássico o primeiro e outro para bater o recorde usando bônus na pista para congelar o cronômetro, nada de novo. Sim, sou um grande fã de CTR. Vou escrever um pequeno tutorial dividido em três artigos sobre como criei um LapManager para lidar com o controle de volta, como uso meu próprio mecanismo de IA simples e como o melhorei para ser desafiador no modo clássico e como implementei a luta contra o relógio.

Primeiramente em nosso motor tudo acontece em um plano 2D, colisões, IA e tudo mais além de modelos 3D. Isso é bastante comum para economizar tempo de computação da CPU em outra dimensão, mas tudo poderia funcionar em um ambiente 3D, em vez de usar polígonos convexos 2D usaríamos cascos convexos 3D ou em vez de usar linhas usaríamos planos, por exemplo. Meu método é uma aproximação para melhorias de desempenho, JavaScript não é particularmente rápido, especialmente em telefones celulares, por isso eu uso segmentos para dividir a rota principal em segmentos, embora alguém possa usar uma curva bezier ou uma curva catmull rom para ser mais preciso Acho que é superengenharia, Mantenha simples!

O gerenciador de voltas registra todos os segmentos de linha para definir a ordem natural da pista.

968714762e63455ea504a8c0d99f7e0d.segments

Basta cadastrar os segmentos para armazená-los em um mapa:

const route_segments_1 = [    { name: 'GvRay2(51,44)' }, { name: 'GvRay2(48,46)' }, { name: 'GvRay2(31,41)' },    { name: 'GvRay2(13,49)' }, { name: 'GvRay2(9,31)'  }, { name: 'GvRay2(14,1)'  },    { name: 'GvRay2(32,9)'  }, { name: 'GvRay2(43,8)'  }, { name: 'GvRay2(51,16)' }];level.lap_manager.set_route( level, route_segments_1 );

Além de registrar todos os navios e atribuir uma rota de direção definida como nós ao seu Agente AI, a rota AI usa pontos no plano 2D:

const route_marks_1 = [     { node: 'GvRaceMark4' }, { node: 'GvRaceMark12' }, { node: 'GvRaceMark1' },    { node: 'GvRaceMark23' }, { node: 'GvRaceMark2' }, { node: 'GvRaceMark34' },    { node: 'GvRaceMark3' } ];        ship_race_1 = level.get_object( 'GvRaceShip1' );ship_race_1.set_auto_route( route_marks_1, 'GvRaceMark4', true, 0.4, 8.0 );level.lap_manager.add_vehicle( ship_race_1 );ship_race_2 = level.get_object( 'GvRaceShip2' );ship_race_2.set_auto_route( route_marks_1, 'GvRaceMark4', true, 0.2, 8.0 );level.lap_manager.add_vehicle( ship_race_2 );ship_race_3 = level.get_object( 'GvRaceShip3' );ship_race_3.set_auto_route( route_marks_1, 'GvRaceMark4', true, 0.3, 8.0 );level.lap_manager.add_vehicle( ship_race_3 );player = level.get_object( 'player' );level.lap_manager.add_vehicle( player );

O gerenciador de volta recebe colisões de raios quando um colisor circular de navio registrado entra em contato com um segmento no nível registrado como segmento de pista. O primeiro segmento é aquele que aumenta a contagem de voltas do navio ou aciona o evento de vitória/derrota. É uma abordagem simples que funciona por enquanto até eu controlar falhas e trapaceiros.

As posições são fixadas assim que os navios terminam a última volta em ordem e não mudam, o desafio é calcular a posição dinâmica dos navios. É tudo uma questão de prioridades, eu pego todos os navios que não terminaram a corrida e ordeno em uma determinada ordem, primeiro vão os navios com mais voltas, se eles tiverem a mesma quantidade de voltas então eu classifico pelo último segmento da corrida que eles vieram, como último recurso se estiverem no mesmo segmento de corrida calculo a distância até o segmento de reta e aquele com maior distância é o que está à frente. É uma aproximação, mas funciona bem o suficiente.

e7d64886b0ad49b58823c77e634abe54.pos by distance

Nada sofisticado, funciona bem se os navios seguirem a rota padrão, se eles pegarem um atalho, o navio pode parecer estar atrás quando os outros navios cruzarem os próximos segmentos de linha, mas uma vez que o jogador astuto consiga o segmento de linha adicional, então ele deverá voltar ao caminho certo, esperançosamente na primeira posição ou recuperando uma boa classificação.

550c48ad7bb24b63b6f61209d35ac7b8.shortcut

O algoritmo não leva em conta

Com informações de GameDev.net.