Domanda

Voglio avere un gioco in cui la vista si sposterà mentre il mouse raggiunge il bordo esterno della finestra (simile a molti giochi RTS). Ho letto che c'è un notevole sovraccarico quando si utilizza MouseMotionListener.

Esiste forse un modo per avere un secondo componente trasparente nella finestra di gioco (JPanel) che non influisce sul gioco, ma si registra quando il mouse lascia il componente interno tramite MouseAdapter.mouseEntered () / mouseExited ()?

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

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

Sono in perdita su come determinare quale confine dello schermo è stato attraversato senza dover avere quattro dei componenti sopra menzionati sovrapposti agli angoli per formare un bordo attorno allo schermo in grado di rilevare se il mouse si trova su qualsiasi bordo o angolo . Immagino che sia abbastanza costoso (dover controllare ogni componente durante l'esecuzione del gioco) ...

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
    }
}

Esattamente quanto overhead esiste con MouseMotionListener? Questo o un metodo simile sarebbero forse più efficienti se i rilevamenti dovessero essere fatti solo lungo i bordi di una finestra di gioco?

NOTA: verrà utilizzato in modalità finestra oltre che possibile applicazione a schermo intero.

È stato utile?

Soluzione

Ho implementato la stessa cosa di cui hai bisogno usando un MouseMotionListener . Non sono davvero sicuro del motivo per cui pensi che aggiungerà overhead ... Se aggiungi uno e chiedi semplicemente a ciascuno dei suoi metodi di stampare sulla console (che è lento) e spostare il mouse, vedrai che è piuttosto scattante dal punto di vista dell'utente.

La mia implementazione consiste in 4 parti principali: un riquadro di scorrimento, regioni rettangolari, un timer e un MouseMotionListener .

In primo luogo, ho creato un pannello, chiamato AutoScrollPane , che estende JScollPane . Anche se è un JScrollPane , puoi nascondere le barre di scorrimento. Questo mi permette di sfruttare la funzionalità per spostare un viewport su una mappa o simile come in un gioco RTS come dici tu.

In secondo luogo, per le regioni di scorrimento, in realtà ho 8: n, ne, e, se, s, sw, w e nw (ovvero "nord", nord-est ", ecc.), con le diagonali che consentono scorrimento diagonale. Li implemento semplicemente come Rectangle s. Non sono disegnati sullo schermo o altro - ho solo un'istanza di 8 rettangoli nella mia classe dimensionati in modo appropriato e con coordinate che corrispondono alle regioni della finestra. In realtà autorizzo il ridimensionamento della mia finestra, quindi, se necessario, ridimensiono i rettangoli.

Terzo, ho un timer che può essere attivato e disattivato. Quando è acceso, ogni "segno di spunta" genera un eseguibile . Questo lavoro Runnable serve a scorrere la finestra del pannello nella direzione appropriata per una certa distanza. Ogni Runnable viene consegnato alla coda degli eventi Swing.

Infine, ho un MouseMotionListener . Il suo compito è intercettare gli eventi di ingresso, uscita e spostamento del mouse. Ogni volta che riceve un evento, controlla la posizione corrente del mouse e se interseca uno dei rettangoli. In base al rettangolo, sceglie una direzione da scorrere. Tiene traccia del fatto che il mouse si trovasse in una regione di scorrimento dell'evento precedente o meno. Sulla base di queste informazioni, sa se dovrebbe iniziare lo scorrimento, interrompere lo scorrimento o lasciare semplicemente che tutto ciò che sta accadendo continui. Volevo che il mio scorrimento si interrompesse se il mouse esce dal riquadro, quindi l'uso degli eventi exit / enter. Ad ogni modo, per iniziare a scorrere, l'ascoltatore salva la direzione e la distanza per scorrere e dice al timer di iniziare. Quando è il momento di interrompere lo scorrimento (ad esempio quando il mouse esce da un'area di scorrimento), indica al timer di arrestarsi.

Ci è voluto un po 'di tempo per scegliere la giusta granularità del timer e la distanza di scorrimento per uno scorrimento uniforme, ma funziona abbastanza bene. Spero che questo schema offra un po 'di aiuto.

Altri suggerimenti

Penso che sia stato Martin Fowler a dichiarare che l'ottimizzazione prematura è la radice di tutto il male nello sviluppo del software. Perché non provare MouseMotionListener e pensare all'ottimizzazione solo se scopri che influisce sulle prestazioni del gioco.

Non c'è niente di sbagliato in un MouseMotionListener Quando leggi l'overhead è stato probabilmente un esempio specifico

Tutto ciò che puoi fare in qualsiasi linguaggio di programmazione può essere fatto male o male.

Se presti attenzione a ciò che fai nel tuo ascoltatore, tutto dovrebbe andare bene

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top