2015-08-23 5 views
5

Quindi per un gioco sto lavorando ho un sacco di chiavi diverse che fanno cose diverse (per esempio il tasto w fa alzare il giocatore e il tasto e fa alzare il carattere verso destra).Come potrei riconoscere 2 pressioni separate dei tasti come una chiave?

Mi chiedo se ci sia un modo per far sì che il tasto W + il tasto D faccia apparire il lettore a destra, anche se quei tasti sono già in uso.

private void FrmGM_KeyDown(object sender, KeyEventArgs e) 
    {    
     if (e.KeyCode == Keys.W) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player1)); 
      bulletnumb = 1; 
     } 

     if (e.KeyCode == Keys.E) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player2)); 
      bulletnumb = 2; 
     } 

     if (e.KeyCode == Keys.D) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player3)); 
      bulletnumb = 3; 
     } 

     if (e.KeyCode == Keys.C) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player4)); 
      bulletnumb = 4; 
     } 

     if (e.KeyCode == Keys.X) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player5)); 
      bulletnumb = 5; 
     } 

     if (e.KeyCode == Keys.Z) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player6)); 
      bulletnumb = 6; 
     } 

     if (e.KeyCode == Keys.A) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player7)); 
      bulletnumb = 7; 
     } 

     if (e.KeyCode == Keys.Q) 
     { 
      picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player8)); 
      bulletnumb = 8; 
     } 

questo è il codice per le mie chiavi preme

+0

La risposta è chiara. Di solito TU sei quello che codifica ciò che dovrebbero fare le chiavi. Mostrarci del codice potrebbe aiutare. – PhilMasterG

risposta

3

La prima linea di offesa per questo genere di cose è solo quello di fare in modo che ogni tasto può essere attivato in concomitanza, e che la combinazione degli effetti della ogni chiave ha il risultato desiderato. Il tuo codice sarà più manutenibile e più facile da scrivere se segui questo approccio, piuttosto che provare a caso speciale l'input della chiave combinata.

Ad esempio, è possibile avere una serie di flag che rappresentano lo stato della chiave corrente e quindi sull'aggiornamento del frame del gioco, controllare tali flag e impostare lo stato dei caratteri sulla cosa corretta (ovvero anziché impostare immagini specifiche nel gestione delle chiavi, come stai facendo ora).

Così si potrebbe avere bandiere come:

bool lookUp, lookRight, lookDown, lookLeft; 

Poi chiave-down per W sarebbe impostare il flag lookUp, mentre il tasto-up per la stessa chiave sarebbe cancellare la bandiera. Allo stesso modo, ad es. per D, per il flag lookRight.

Quindi, durante l'aggiornamento del frame di gioco, controlli le bandiere. Se lookUp e lookRight sono entrambi impostati, quindi si utilizza l'immagine "look up and right". Se sono impostati solo uno o l'altro contrassegno, si utilizza la grafica "look up" o "look right". Allo stesso modo per le altre chiavi e le loro combinazioni. Potresti persino risolvere lookUp e lookDown o lookLeft e lookRight, come qualunque sia l'immagine predefinita (ad esempio se l'utente non ha premuto alcun tasto).


Si noti che se si desidera utilizzare p/invoke, è possibile utilizzare la funzione GetAsyncKeyState() e non preoccuparsi nemmeno dell'evento di ridimensionamento. Basta controllare lo stato della chiave prima di ogni aggiornamento del frame per il gioco e aggiornare la grafica in base allo stato attuale della tastiera. In questo modo, si consente a Windows di eseguire tutto il monitoraggio dello stato delle chiavi e non si perde tempo a tenere traccia dello stato della chiave che non ha importanza (ad esempio se l'utente causa più modifiche allo stato della chiave tra i frame).


Detto questo, se non si può/non farà una di queste, allora sì ... tutto quello che dovete fare è controllare per la combinazione prima (vale a dire che hai la-down chiave sia per , senza una key-up per il tasto premuto inizialmente della combinazione).

Ricorda che prendere questo approccio significa che continuerai a prendere l'effetto per il primo tasto premuto, quindi devi passare all'effetto di combinazione.

4

Memorizza le lettere in un set quando arrivano gli eventi KeyDown e li rimuove nel gestore di eventi KeyUp.In questo modo il KeyDown sarebbe in grado di "vedere" se la "chiave compagno" è stato premuto:

private readonly ISet<char> keysCurrentlyDown = new HashSet<char>(); 

private void FrmGM_KeyDown(object sender, KeyEventArgs e) {    
    if (e.KeyCode == Keys.W) 
    { 
     if (keysCurrentlyDown.Contains('D')) { 
      // Call some method to handle W+D 
     } else { 
      ... 
     } 
     keysCurrentlyDown.Add('W'); 
    } else if (e.KeyCode == Keys.D) 
    { 
     if (keysCurrentlyDown.Contains('W')) { 
      // Call some method to handle W+D 
     } else { 
      ... 
     } 
     keysCurrentlyDown.Add('D'); 
    } 
    ... 
} 
private void FrmGM_KeyUp(object sender, KeyEventArgs e) {    
    if (e.KeyCode == Keys.W) { 
     keysCurrentlyDown.Remove('W'); 
    } else if (e.KeyCode == Keys.D) { 
     keysCurrentlyDown.Remove('D'); 
    } ... 
} 

} 
+0

Che cos'è il tipo "Set " che stai utilizzando? Si noti che mantenendo la gestione dello stato visivo all'interno della gestione degli input da tastiera, si finisce per duplicare lo sforzo (ad esempio si hanno due posizioni diverse da gestire "Fai qualcosa su W + D"). –

+0

@PeterDuniho Questo è il 'ISet ', grazie. Per quanto riguarda la gestione di W + D contro D + W, avrei dovuto commentare più attentamente: qualunque sia l'azione su W + D dovrebbe essere, il codice dovrebbe essere inserito in un metodo per evitare la duplicazione del codice. – dasblinkenlight

+0

Ancora si verifica la condizione W + D in due diversi posti (anche se in ordine diverso ogni volta) e, naturalmente, mentre l'implementazione può essere incapsulata in un unico metodo, è comunque necessario chiamarla da due punti diversi. Sarebbe meglio controllare semplicemente lo stato della tastiera una volta che tutto l'input è stato elaborato, e appena prima dell'aggiornamento per il frame corrente. –

0

utilizzare il

PresentationCore.dll e la WindowsBase.dll come riferimento in il tuo progetto

PresentationCore.dll ha una tastiera - Classe e WindowsBase.dll ha una Key - Class.

poi:

using System; 
    using System.Windows.Forms; 
    using System.Windows.Input; 

      namespace ViewTest 
      { 
       public partial class ViewTest : Form 
       { 
        private void ViewTest_KeyDown(object sender, KeyEventArgs e) 
        { 
         if (Keyboard.IsKeyDown(System.Windows.Input.Key.W) && 
          Keyboard.IsKeyDown(System.Windows.Input.Key.D)) 
         { 
          // do something 
         } 
        } 
      } 

è un modo semplice per farlo :)

+0

Quindi, all'evento _every_ key-down, stai suggerendo la combinazione di tasti _every_ possibile controllo OP? Uh ... sembra un po 'non ottimale, per non dire altro. –

+0

anche quello che sta facendo ora – Ryfang

+0

Sì, ma il suo codice potrebbe essere convertito in un 'switch' (e dovrebbe essere), e quindi sarebbe più efficiente. Quanto sopra non può essere. Nota anche che non ci sono indicazioni nell'OP che stia usando WPF. In effetti, assomiglia molto a Winforms. Anche il trascinamento nelle DLL WPF solo per la gestione dello stato delle chiavi non è molto efficiente. –

-1

Guardare in sovrascrivendo il ProcessCmdKey

protected override bool ProcessCmdKey(ref Message m, Keys k) 
{ 
    if (k == (Keys.Control | Keys.D)) 
    { 
     MessageBox.Show("CTRL+D"); 

     return true; 
    } 

    return base.ProcessCmdKey(ref m, k); 
} 
Problemi correlati