Positionnement des indicateurs à l'écran pour pointer vers des cibles hors écran

Dans les jeux de défilement 2D (et certains jeux 3D), vous aurez souvent besoin d'indiquer au joueur l'emplacement d'une cible hors écran, qu'il s'agisse d'un ennemi, d'un allié ou d'un objectif de jeu. De nombreux jeux utilisent une flèche qui flotte près du bord de l'écran pour indiquer la direction dans laquelle se trouve la cible. Dans ce didacticiel, je vais expliquer une méthode qui utilise une algèbre simple pour trouver où placer un tel indicateur..


Forme d'interception de pente


La forme d'interception de pente est une façon de décrire une ligne droite en 2D avec une algèbre linéaire. Il utilise un pente, qui utilise normalement le symbole m, qui définit la pente de la ligne, et un décalage ou intercepter, qui utilise le symbole b, qui définit l'endroit où la ligne croise l'axe des y.

\ [y = mx + b \]

Grâce à cette relation, si nous avons une valeur, nous pouvons utiliser l’équation générale pour calculer facilement l’autre valeur, à la fois conceptuellement et mathématiquement..

Puisque nous trouvons la position par rapport à l'écran - une surface plane - nous effectuons tous les calculs en 2D, même si le jeu est en 3D..

Pointe: Si vous travaillez en 3D, vous devez transformer l'emplacement du monde en emplacement de l'écran de votre objet 3D. La plupart des moteurs traditionnels ont des fonctions intégrées pour le faire; consultez la documentation de votre moteur pour plus d'informations.

Si nous pouvons trouver une ligne à l'écran décrivant la direction dans laquelle l'objet que nous visons se trouve, nous pouvons déterminer le point où il traverse un bord donné, puis utiliser un peu d'essais et d'erreurs pour déterminer de quel côté de l'écran il se trouvera. attaché à.


Faire des hypothèses


Si nous imaginons que notre écran est sur une grille et que le point d'origine (0, 0) est juste au centre de l'écran, alors il est facile de calculer les valeurs qui décrivent la ligne.

Puisque la ligne passera par le centre, nous savons que notre interception, b, doit être zéro. Et si la grille est placée comme ça, on peut très facilement calculer la pente, m: c'est simplement la cible y/X. (Dans l'image ci-dessus, notre cible est le curseur de la souris.)

Une fois que nous avons la pente, nous pouvons utiliser la substitution pour calculer où la ligne franchirait les limites de l'écran. Par exemple, si nous voulons trouver quelle est la valeur y au point où la ligne traverse le bord de l'écran, nous utilisons le formulaire d'origine. y = mx, où X est réglé sur le bord de l'écran. Si nous voulions savoir où il croise le haut ou le bas de l'écran, nous divisons les deux côtés par m de sorte que l'équation devient: x = y / m - alors nous venons de définir y au bord de l'écran.

Tandis que la grille est placée de cette manière, le bord de l'écran correspondrait à la moitié de la largeur de l'écran, négatif pour gauche et positif pour droite. De même pour l’axe vertical, le bord de l’écran est à la moitié de sa hauteur, mais que le haut soit positif ou négatif peut varier d’un moteur à l’autre..

Ainsi, un jeu 800x600px aura ses bords de l'écran à x = -400px, x = + 400px, y = -300px, et y = + 300px.


Espace de coordonnées

Ce qui précède conviendrait si l’origine du système de coordonnées était le centre de l’écran, mais c’est rarement le cas. La plupart des moteurs ont leur origine dans le coin supérieur gauche ou inférieur gauche.

Avant de faire nos calculs, nous devons déplacer notre espace de coordonnées afin que toutes nos valeurs soient relatives au centre de l'écran plutôt qu'à l'origine par défaut utilisée par notre moteur.

Déplacement de l'espace de coordonnées. Points non à l'échelle.

Son complexe? Pas vraiment. Nous avons juste besoin de savoir combien nous voulons déplacer l’espace de coordonnées et de le soustraire de notre position cible. Donc, si nous voulons déplacer notre grille vers le haut de la moitié de la largeur de l’écran, nous soustrayons la moitié de la largeur de l’écran de la cible. y valeur.


En voici un que j'ai préparé plus tôt

Dans l'exemple ci-dessus, la taille de l'écran est 800x600px, l'espace de coordonnées étant décalé de sorte que (0, 0) est au centre du moniteur. La cible hors écran est à (800, 400) en utilisant le même espace de coordonnées.

Puisque la coordonnée y de la cible est positive (et que, dans ce moteur, l'axe des y est dirigé vers le haut), nous savons que ce ne sera pas sur le bord inférieur de l'écran. Nous avons donc initialement trouvé sa position sur le bord supérieur de l'écran. , lequel est (600, 300).

Nous pouvons mathématiquement dire que ce point est toujours hors écran car sa coordonnée x (600) est supérieure à la moitié de la largeur (800/2 = 400), nous allons ensuite chercher sa position sur le côté de l'écran.

Encore une fois, il suffit de vérifier un côté de l’écran, car si notre coordonnée x est positive, le point doit se trouver du côté droit de l’écran. (Si c'était négatif, il faudrait que ce soit du côté gauche.)

Une fois que nous trouvons le point sur le côté droit de l'écran - (400, 200) - nous savons que doit être correct, car nous avons exclu tous les autres côtés de l'écran par un processus d'élimination.


Ajouter une petite pointe de trigonométrie

En plus de positionner l'indicateur, vous pouvez également le faire pivoter pour obtenir un effet supplémentaire, en particulier s'il s'agit d'une flèche. Il existe une fonction pratique faisant partie de la plupart des cours de mathématiques qui résout ce problème assez facilement: atan2 ().

le atan2 () La fonction prend deux paramètres: une coordonnée x et une coordonnée y. Il retourne un angle qui indique la direction de (0, 0) à (x, y).

 rotation = Math.atan2 (centerMouse.top, centerMouse.left); rotation = rotation * 180 / Math.PI; // convertit les radians en degrés

Il y a plusieurs choses à garder à l'esprit avec atan2 () cela peut varier entre les langues et les moteurs. Premièrement, les arguments sont souvent atan2 (y, x), alors que la plupart des autres fonctions mathématiques prennent d'abord la coordonnée x. De plus, la rotation est souvent renvoyée en radians plutôt qu'en degrés.

Pointe: Je ne vais pas entrer dans les différences entre les radians et les degrés, sauf pour dire que la conversion de l'un à l'autre est facile: il vous suffit de multiplier les radians par (180 / Pi) pour les transformer en degrés, et les multiplier par (Pi / 180) si vous voulez les changer.


Derniers contrôles

Il reste une dernière chose à vérifier avant de créer un indicateur hors écran: il s’agit de savoir si notre cible est réellement hors écran, car il n’a pas beaucoup de sens de pointer dans la direction de notre cible si nous pouvons déjà voir notre cible. Encore une fois, nous allons utiliser des calculs assez simples pour résoudre ce problème.

Puisque notre écran est un rectangle non marqué, nous n’avons rien à faire avec les angles, nous devons simplement vérifier si notre point cible est plus bas que le haut, plus haut que le bas, à gauche du bord droit, et à droite du bord gauche de l'écran.

var screen = width: 200; hauteur: 100 // alerte de valeurs factices (isTargetOnScreen (left: 50; top: 60)); // True alert (isTargetOnScreen (left: 250; top: 10)); // False function isTargetOnScreen (cible) if (cible.top> 0 && cible.top < screen.height && target.left < screen.width && target.left > 0) // la cible est à l'écran, utilise une superposition ou ne fait rien. retourne vrai;  else // la cible est hors écran, recherchez la position de l'indicateur. retourne faux; 

En utilisant les valeurs factices ci-dessus, nous constatons que la cible est à l'écran. Ces valeurs peuvent provenir de n’importe quel endroit stockant des informations sur l’objet que vous suivez..

Notez que le code ci-dessus suppose que nous sommes dans l’espace de coordonnées où (0, 0) est dans le coin de l'écran, comme la plupart des moteurs auront par défaut. Par conséquent, cette étape doit être effectuée avant de décaler l'espace de coordonnées vers le centre, comme nous le faisons lors du calcul de la position de l'indicateur..


Mettre tous ensemble

Voici une démonstration rapide pour montrer ces concepts en action (voir le code sur GitHub):

Passons en revue le code:

  • Tout d'abord, nous vérifions si la cible est réellement hors écran; si c'est à l'écran, nous savons déjà où placer le curseur, si nous voulons le faire.
  • Nous changeons l'espace de coordonnées pour que l'origine soit au centre de l'écran.
  • En regardant la position de la souris, on peut facilement savoir si c'est dans la moitié supérieure ou inférieure de l'écran.
  • En utilisant cette information, et la substitution algébrique, nous calculons où ce point serait situé en haut ou en bas de l'écran.
  • Nous regardons le point que nous venons de calculer et vérifions s'il s'agit bien d'une position à l'écran ou si elle est trop éloignée à gauche ou à droite.
  • Si le point est hors écran, nous calculons un nouveau point sur le côté de l'écran, au lieu du haut ou du bas.
  • Nous devrions maintenant avoir le bon point dans le mauvais espace de coordonnées, nous faisons donc l'inverse de ce que nous avons fait dans la première étape pour le ramener dans le bon système de coordonnées.

Conclusion

Voilà un extrait de code pratique à ajouter à l'interface utilisateur de votre jeu. Maintenant que vous pouvez diriger le joueur dans la direction d'une cible, réfléchissez également à la manière dont vous pourriez afficher la distance..