Comment gérer les différences entre les coordonnées d'écran 2D et les coordonnées cartésiennes

23
  • La plupart des systèmes de coordonnées 2D écran / bitmap ont l'axe Y positif pointant vers le bas (avec l'origine dans le coin supérieur gauche).
  • C'est contraire à la façon dont la plupart des gens pensent géométriquement avec l'axe Y positif pointant vers le haut (avec l'origine au centre).

Comment la plupart des jeux gèrent-ils les deux systèmes de coordonnées 2D différents? Il existe deux principaux types de coordonnées (écran vs cartésien), mais il peut y avoir de nombreux espaces de coordonnées différents: espace sprite, espace monde, espace vue, espace écran, etc ...

Contexte:

À l'origine, j'ai fait correspondre les coordonnées du monde dans mon jeu à la convention des coordonnées d'écran 2D. Cela rendait très naturel l'utilisation des routines de dessin graphique, mais des problèmes subtils se posaient lors de l'utilisation de fonctions trigonométriques comme atan2 (). Les résultats de l'alimentation des coordonnées d'écran 2D de atan2 () sont très déroutants car atan2 () suppose que l'axe y positif pointe vers le haut.

J'ai donc changé mes coordonnées universelles pour suivre le système de coordonnées cartésiennes classique (avec l'origine en bas à gauche de l'écran). Le raisonnement avec atan2 () est beaucoup plus simple, mais maintenant il est plus difficile de faire d'autres types de raisonnement:

  • Si je clique sur l'écran ici, quel sprite est en dessous?
  • Où ai-je cliqué sur ce sprite?
  • Si un sprite est dessiné au mauvais endroit, qu'est-ce qui a été calculé incorrectement? Les coordonnées de l'écran ou les coordonnées du monde?

Je réalise que la conversion de l'écran en coordonnées cartésiennes implique simplement de mettre à l'échelle la valeur y de -1 avec une traduction facultative des deux valeurs (x, y). Je suis plus intéressé par les meilleures pratiques de conception de jeux:

  • La plupart des jeux respectent-ils simplement la convention des coordonnées d'écran et changent-ils leur façon de penser comment des choses comme atan2 () devraient fonctionner?
  • Quand / comment les conversions de système de coordonnées sont-elles effectuées? (Utilisation de matrices, abstraction OOP, etc.)
  • Les emplacements des images-objets sont-ils stockés au centre de l'image-objet ou dans l'un des coins? La hauteur / largeur du sprite allant dans la «mauvaise» direction semble être un problème courant lorsque je les dessine.

Bien que ma question concerne principalement les jeux 2D, il semble qu'OpenGL utilise un système de coordonnées où l'axe Y pointe vers le haut. OpenGL doit éventuellement projeter ces coordonnées 3D sur un système de coordonnées d'écran 2D. Peut-être que quelques conseils pourraient être trouvés dans la méthode d'OpenGL ...

Leftium
la source

Réponses:

8

Après avoir essayé toutes les façons imaginables de le faire, j'ai trouvé que si c'était purement un jeu 2D, utilisez simplement le système de dessin d'écran, cela vous facilitera la vie. Sin, Cos et atan2 doivent être utilisés légèrement différemment, mais cet inconvénient est facilement compensé par la simplicité de savoir dans quelle direction monter, descendre, dans le sens horaire et anti-horaire. Je recommanderais également de travailler en pixels plutôt qu'en mètres pour les jeux 2D - il est beaucoup plus facile de penser aux distances à l'écran, et les chances que vous souhaitiez changer toute l'échelle de votre jeu sont proches de zéro.

"Comment la plupart des jeux gèrent-ils les deux systèmes de coordonnées 2D différents?"

  • la plupart des jeux 2D dont j'ai vu la source pour utiliser le système d'écran, mais chaque entité devrait connaître son espace mondial, laissez votre gestionnaire de dessin le convertir en position d'écran. À ce stade, vous ferez la transformation de matrice dont vous avez besoin.

"Les emplacements des sprites sont-ils stockés au centre du sprite ou dans l'un des coins?"

  • Si vous travaillez à partir du centre, cela rend la rotation plus simple, bien que vous souhaitiez également connaître les coins.

"Peut-être que des conseils pourraient être trouvés dans la méthode d'OpenGL ..."

  • Les moteurs 3D sont un cas complètement différent. Comme ils ont de vraies caméras, la position de l'écran peut être très différente de la position mondiale. Pour un jeu descendant, vous travailleriez dans les axes X et Z, plutôt que X et Y pour une chose.
Iain
la source
1

Je simplifie peut-être trop les choses ici, mais mon inclination serait d'avoir tout sous-système 2D / UI strictement dans ce que vous avez appelé les coordonnées "écran". Vous auriez deux matrices: ScreenToCartesianTransform et CartesianToScreenTransform. Lorsque des événements d'entrée de souris sont reçus, les coordonnées de la souris sont transformées à l'aide de CartesianToScreenTransform avant d'être transmises au gestionnaire d'entrée du système 2D / UI. À partir de là, le système d'interface utilisateur effectuerait des tests de réussite à l'aide du système de coordonnées d'écran et gérerait (ou non) l'événement en conséquence. Si un événement d'entrée de souris n'est pas géré par la 2D / UI, il peut être transmis au système 3D (s'il en existe un) en utilisant les coordonnées d'origine non transformées.

Comme le système 2D / UI ne traiterait que des coordonnées "écran", sa géométrie devrait être transformée via ScreenToCartesianTransform avant d'être traitée par le moteur de rendu.

Mike Strobel
la source
En fait, selon la boîte à outils que vous utilisez, les événements d'entrée de la souris peuvent déjà être en coordonnées d'écran. Dans ce cas, vous ne les transformeriez pas pour le système 2D / UI, mais vous le feriez pour le système 3D (s'il en existe un).
Mike Strobel
0

Je préfère utiliser une arborescence d'affichage comme dans Flash. J'aurai un nœud racine (vue de jeu) qui contient un enfant pour le monde (nœud mondial) et un en haut pour le HUD. À l'intérieur du nœud du monde seront les nœuds des objets du monde du jeu.

Je transforme ensuite simplement le nœud mondial. En plus de la traduction (panoramique de la caméra) et de la mise à l'échelle proportionnelle (zoom de la caméra), j'applique également deux autres transformations:

  • Une échelle de -1 pour inverser le système de coordonnées.
  • Une mise à l'échelle pour convertir les unités mondiales (mètres) en unités d'écran (pixels)

J'utilise ensuite les coordonnées y-up / world dans le code de dessin d'objet de jeu et les coordonnées y-down / screen dans le code de dessin HUD, qui semblent toutes les deux très naturelles.

Pour répondre à des questions telles que "sur quel objet suis-je en train de cliquer", j'utilise des méthodes de noeud d'affichage pour convertir les coordonnées entre les systèmes de coordonnées (comme globalToLocalet son inverse dans Flash).

Soit dit en passant, atancela ne fonctionne pas vraiment différemment lorsque y est en baisse, il vous suffit de penser que tous les angles vont dans le sens horaire plutôt que dans le sens antihoraire.

Bart van Heukelom
la source
0

OpenGL, comme DirectX, a les axes X et Z le long du plan horizontal et Y vers le haut.
Je n'ai jamais eu de problème avec les coordonnées d'écran, et je pense que la façon la plus simple serait simplement de la traiter telle qu'elle est: si quelque chose, comme atan2, ne l'aime pas, alors changez les paramètres en cours d'alimentation.

Si vous utilisez des coordonnées relatives ou locales, comme un graphique de scène, alors une fonction simple telle que ToGlobalCoords () est bonne. En fait, si vous voulez en savoir plus sur le positionnement spatial, les graphiques de scène et localToGlobal, l'extrait gratuit de Game Engine Architecture est à ce sujet.

Les sprites sont dessinés à partir du coin supérieur gauche ou (0,0) de l'origine. Les raisons en sont à cause de l'origine en haut à gauche de la fenêtre.

Il semble un peu idiot de changer le système de coordonnées de la fenêtre et rendrait les choses comme la saisie, qui joue un rôle plus important pour la plupart des jeux que le trig, beaucoup plus difficile. Il vous éloigne également de la norme et des utilisateurs de votre code.

Le canard communiste
la source