Question

Je souhaite un jeu dans lequel la vue se déplace lorsque la souris atteint le bord extérieur de la fenêtre (comme dans de nombreux jeux RTS). J'ai lu que l'utilisation de MouseMotionListener entraînait une surcharge importante.

Existe-t-il un moyen d’avoir un deuxième composant transparent dans la fenêtre de jeu (JPanel) qui n’affecte pas le jeu, mais sera enregistré lorsque la souris quitte le composant interne via MouseAdapter.mouseEntered () / mouseExited ()?

boolean mouseOnScreen;
boolean mouseWithinInnerComponent; //is (10 <= mouse.x <= screenWidth - 10) && (10 <= mouse.y <= screenHeight)

if(mouseOnScreen && !mouseWithinInnerComponent)
{
    //do something...
}

Je ne sais pas comment déterminer quelle limite d'écran a été franchie sans qu'il soit nécessaire que quatre des composants mentionnés ci-dessus se chevauchent pour former une bordure autour de l'écran permettant de détecter si la souris se trouve à un bord ou un coin . J'imagine que cela coûte assez cher (devoir vérifier chaque composant lors de l'exécution du jeu) ...

boolean mouseOnScreen;
boolean mouseWithinTopComponent; //is (0 <= mouse.y <= 10)
boolean mouseWithinBottomComponent; //is (screenHeight - 10 <= mouse.y <= screenHeight)
boolean mouseWithinLeftComponent; //is (0 <= mouse.x <= 10)
boolean mouseWithinRightComponent; //is (screenWidth - 10 <= mouse.x <= screenWidth)

if(mouseOnScreen)
{
    if(!mouseWithinBottomComponent)
    {
        //move view up
    }
    if(!mouseWithinTopComponent)
    {
        //move view down
    }
    if(!mouseWithinLeftComponent)
    {
        //move view right
    }
    if(!mouseWithinRightComponent)
    {
        //move view left
    }
}

Existe-t-il une surcharge avec MouseMotionListener? Est-ce que cette méthode ou une méthode similaire serait peut-être plus efficace si les détections devaient uniquement être effectuées le long des bordures d'une fenêtre de jeu?

REMARQUE: cette option sera utilisée en mode fenêtré, ainsi que pour une application possible en plein écran.

Était-ce utile?

La solution

J'ai mis en œuvre la même chose dont vous avez besoin en utilisant un MouseMotionListener . Je ne sais pas vraiment pourquoi vous pensez que cela va ajouter des frais supplémentaires ... Si vous en ajoutez une et demandez simplement à chacune de ses méthodes d'imprimer sur la console (ce qui est lent) et de déplacer votre souris, vous verrez que c'est plutôt vif du point de vue de l'utilisateur.

Mon implémentation comprend 4 éléments principaux: un volet de défilement, des régions rectangulaires, un minuteur et un MouseMotionListener .

Tout d'abord, j'ai créé un panneau, appelé AutoScrollPane , qui étend JScollPane . Même s'il s'agit d'un JScrollPane , vous pouvez masquer les barres de défilement. Cela me permet de tirer parti des fonctionnalités permettant de déplacer une fenêtre d'affichage sur une carte ou similaire, comme dans un jeu RTS, comme vous le dites.

Deuxièmement, pour les régions de défilement, j’ai en fait 8: n, ne, e, se, s, sw, w et nw (c’est-à-dire "nord", nord-est ", etc.), les diagonales permettant défilement diagonal. Je les implémente simplement en tant que Rectangle . Ils ne sont pas dessinés à l'écran ou quoi que ce soit - je viens d'instancier 8 rectangles dans ma classe, de taille appropriée et avec des coordonnées qui correspondent aux régions de la fenêtre. J'autorise en fait le redimensionnement de ma fenêtre, donc je redimensionne les rectangles si nécessaire.

Troisièmement, j'ai une minuterie qui peut être activée et désactivée. Lorsqu'il est activé, chaque "tic-té" génère un Runnable . La tâche de Runnable consiste à faire défiler la fenêtre de visualisation du panneau dans la direction appropriée, à une certaine distance. Chaque Runnable est remis à la file d'attente des événements Swing.

Enfin, j'ai un MouseMotionListener . Son travail consiste à intercepter les événements d’entrée, de sortie et de déplacement de la souris. Chaque fois qu'il reçoit un événement, il vérifie l'emplacement actuel de la souris et s'il croise l'un des rectangles. En fonction de ce rectangle, il choisit une direction de défilement. Il enregistre si la souris était ou non dans une zone de défilement de l'événement précédent. Sur la base de ces informations, il sait s'il doit commencer à faire défiler, arrêter de faire défiler ou tout simplement laisser continuer ce qui se passe. Je voulais que mon défilement s'arrête si la souris sort du volet, d'où l'utilisation des événements exit / enter. Quoi qu'il en soit, pour commencer à faire défiler, l'auditeur enregistre la direction et la distance à parcourir et indique à la minuterie de démarrer. Lorsqu'il est temps d'arrêter de faire défiler le texte (par exemple, lorsque la souris quitte une zone de défilement), elle indique au minuteur de s'arrêter.

Il a fallu un certain temps pour choisir la granularité de minuterie et la distance de défilement appropriées pour un défilement régulier, mais cela fonctionne plutôt bien. J'espère que ces grandes lignes vous aideront.

Autres conseils

Je pense que c’est Martin Fowler qui a affirmé que l’optimisation prématurée est la racine de tous les maux du développement logiciel. Pourquoi ne pas essayer MouseMotionListener et ne penser à l'optimisation que si vous trouvez que cela affecte les performances du jeu.

Il n'y a rien de mal avec MouseMotionListener Lorsque vous avez entendu parler des frais généraux, il s'agissait probablement d'un exemple spécifique

Tout ce que vous pouvez faire dans n'importe quel langage de programmation peut être mal fait ou mal.

Si vous faites attention à ce que vous faites dans votre auditeur, tout devrait bien se passer

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top