Como lidar com diferenças entre coordenadas de tela 2D e coordenadas cartesianas

23
  • A maioria dos sistemas de coordenadas de tela / bitmap 2D tem o eixo Y positivo apontando para baixo (com a origem no canto superior esquerdo).
  • Isso é contrário à maneira como a maioria das pessoas pensa geometricamente com o eixo Y positivo apontando para cima (com a origem no centro).

Como a maioria dos jogos gerencia os dois sistemas de coordenadas 2D diferentes? Existem dois tipos principais de coordenadas (tela vs. cartesiana), mas pode haver muitos espaços de coordenadas diferentes: espaço de sprite, espaço do mundo, espaço de visualização, espaço da tela, etc.

Fundo:

Originalmente, fiz com que as coordenadas do mundo no meu jogo correspondessem à convenção de coordenadas da tela 2D. Isso tornou muito natural o uso das rotinas de desenho gráfico, mas surgiram problemas sutis ao usar funções trigonométricas como atan2 (). Os resultados da alimentação das coordenadas da tela atan2 () 2D são muito confusos porque atan2 () assume que o eixo y positivo aponta para cima.

Então mudei minhas coordenadas mundiais para seguir o sistema de coordenadas cartesianas clássico (com a origem na parte inferior esquerda da tela). O raciocínio com atan2 () é muito mais direto, mas agora é mais difícil executar outros tipos de raciocínio:

  • Se eu clicar na tela aqui, qual sprite está por baixo?
  • Onde eu cliquei nesse sprite?
  • Se um sprite é desenhado no local errado, o que foi calculado incorretamente? A tela coordena ou o mundo coordena?

Percebo que a conversão da tela para coordenadas cartesianas envolve simplesmente escalar o valor de y em -1 com uma tradução opcional de ambos os valores (x, y). Estou mais interessado nas práticas recomendadas para design de jogos:

  • A maioria dos jogos segue a convenção de coordenadas da tela e muda seu pensamento sobre como coisas como atan2 () devem funcionar?
  • Quando / como são feitas as conversões do sistema de coordenadas? (Usando matrizes, abstração OOP, etc)
  • Os locais dos sprites são armazenados como o centro do sprite ou um dos cantos? A altura / largura do sprite indo na direção "errada" parece ser um problema comum quando os desenho.

Embora minha pergunta seja principalmente sobre jogos 2D, parece que o OpenGL usa um sistema de coordenadas em que o eixo Y aponta para cima. O OpenGL deve eventualmente projetar essas coordenadas 3D em um sistema de coordenadas da tela 2D. Talvez alguma orientação possa ser encontrada no método OpenGL ...

Leftium
fonte

Respostas:

8

Tendo tentado todas as formas possíveis de fazê-lo, descobri que se é puramente um jogo 2D, basta usar o sistema de desenho de tela, que facilitará sua vida. Sin, Cos e atan2 precisam ser usados ​​de maneira um pouco diferente, mas esse inconveniente é facilmente compensado pela simplicidade de saber em que direção estão os pontos acima, abaixo, horário e anti-horário. Eu também recomendaria trabalhar em pixels em vez de metros em jogos 2D - é muito mais fácil pensar nas distâncias na tela, e as chances de você querer alterar toda a escala do seu jogo são próximas de zero.

"Como a maioria dos jogos gerencia os dois sistemas de coordenadas 2D diferentes?"

  • Na maioria dos jogos em 2D que eu já vi a fonte para usar o sistema de tela, mas cada entidade deve conhecer seu espaço mundial, deixe seu gerente de desenho converter isso em uma posição na tela. Nesse ponto, você fará a transformação da matriz que precisar.

"Os locais dos sprites são armazenados como o centro do sprite ou um dos cantos?"

  • Se você trabalha a partir do centro, torna a rotação mais direta, embora você queira conhecer os cantos também.

"Talvez alguma orientação possa ser encontrada no método OpenGL ..."

  • Os motores 3D são um caso completamente diferente. Como possuem câmeras verdadeiras, a posição da tela pode ser totalmente diferente da posição mundial. Para um jogo de cima para baixo, você estaria trabalhando nos eixos X e Z, em vez de X e Y, por um lado.
Iain
fonte
1

Talvez eu esteja simplificando demais as coisas aqui, mas minha intenção seria fazer com que qualquer subsistema 2D / UI lidasse estritamente no que você chamou de coordenadas de "tela". Você teria duas matrizes: ScreenToCartesianTransform e CartesianToScreenTransform. Quando os eventos de entrada do mouse são recebidos, as coordenadas do mouse são transformadas usando CartesianToScreenTransform antes de serem passadas para o gerenciador de entrada do sistema 2D / UI. A partir daí, o sistema da interface do usuário executaria o teste de acerto usando o sistema de coordenadas da tela e manipularia (ou não trataria) o evento de acordo. Se um evento de entrada do mouse não for tratado pelo 2D / UI, ele poderá ser transmitido para o sistema 3D (se houver) usando as coordenadas originais não transformadas.

Como o sistema 2D / UI lidaria apenas com as coordenadas da "tela", sua geometria precisaria ser transformada via ScreenToCartesianTransform antes de ser processada pelo mecanismo de renderização.

Mike Strobel
fonte
Na verdade, dependendo do kit de ferramentas que você está usando, os eventos de entrada do mouse já podem estar nas coordenadas da tela. Nesse caso, você não os transformaria para o sistema 2D / UI, mas sim para o sistema 3D (se existir).
Mike Strobel
0

Eu prefiro usar uma árvore de exibição como no Flash. Vou ter um nó raiz (visão do jogo) que contém um filho para o mundo (nó do mundo) e um no topo para o HUD. Dentro do nó do mundo, estarão os nós dos objetos no mundo do jogo.

Eu simplesmente transformo o nó do mundo. Junto com a tradução (panning da câmera) e a escala proporcional (zoom da câmera), também aplico duas outras transformações:

  • Uma escala y de -1 para inverter o sistema de coordenadas.
  • Uma escala para converter unidades mundiais (metros) em unidades de tela (pixels)

Em seguida, uso as coordenadas y-up / world no código de desenho do objeto de jogo e as coordenadas y-down / screen no código de desenho HUD, que parecem naturais.

Para responder perguntas como "em que objeto estou clicando", uso métodos de nó de exibição para converter coordenadas entre sistemas de coordenadas (como globalToLocale sua inversa no Flash).

A propósito, atan realmente não funciona de maneira diferente quando y está baixo, você só precisa pensar em todos os ângulos no sentido horário, e não no sentido anti-horário.

Bart van Heukelom
fonte
0

O OpenGL, como o DirectX, possui os eixos X e Z ao longo do plano horizontal e Y voltados para cima.
Eu nunca tive problemas com as coordenadas da tela e acho que a maneira mais fácil seria simplesmente tratá-lo como é: se algo, como o atan2, não gostar, altere os parâmetros que estão sendo alimentados.

Se você estiver usando coordenadas relativas ou locais, como um gráfico de cena, uma função simples como ToGlobalCoords () é boa. De fato, se você quiser aprender mais sobre posicionamento espacial, gráficos de cena e localToGlobal, a extração gratuita da Game Engine Architecture é sobre isso.

Os sprites são desenhados no canto superior esquerdo ou (0,0) na origem. Razões pelas quais são devido à origem superior esquerda da janela.

Parece um pouco tolo alterar o sistema de coordenadas da janela e tornaria coisas como entrada, que desempenham um papel maior na maioria dos jogos do que o trig, significativamente mais difícil. Também o afasta da norma e de qualquer usuário do seu código.

O Pato Comunista
fonte