2010-09-11 11 views
24

Ho il seguente problema: Sto provando a scrivere un gioco javascript e il carattere è controllato dai tasti freccia.
Il problema è che, quando si tiene premuto il tasto, c'è un breve intervallo tra l'accensione del primo tasto e il kepress ripetuto.
Inoltre, quando si preme il "tasto freccia destra" e lo si tiene premuto, quindi si preme il "tasto freccia su", il personaggio non si sposta nell'angolo in alto a destra, ma arresta il movimento nella direzione corretta e inizia a muoversi su.
Questo è il codice che sto usando:remove key press delay in javascript

<body onLoad="Load()" onKeyDown="Pressed(event)"> 
 
function Pressed(e) { 
     cxc = e.keyCode; 
     if(cxc == 37) 
      Move(-1,0); 
     if(cxc == 38) 
      Move(0,-1); 
     if(cxc == 39) 
      Move(1,0); 
     if(cxc == 40) 
      Move(0,1); 
    } 

Qualcuno ha un'idea ??

+0

il tuo codice non funzionerà, questo è sicuro. Non sono sicuro che tu possa provare che due tasti siano premuti contemporaneamente in JS. aspetterò le risposte. –

+0

bene, lo fa in atto, ma non come previsto. Il mio gioco è un gioco basato sul timer, e la sospensione di 1 secondo aspettando che i tasti ripetuti non vadano bene. È frustrante. – alex

+0

perché non provare a utilizzare un approccio basato su flash. un flash swf trasparente che cattura gli eventi e quindi chiama di conseguenza JS. http://www.java2s.com/Code/Flash-Flex-ActionScript/Development/UpLeftSensor.htm –

risposta

27

Se si desidera la ripetizione dei tasti in modo controllabile, si dovrà implementare da soli, come eventi di pressione sono sparati dipende l'idea del sistema operativo di come chiavi devono ripetere. Ciò significa che potrebbero esserci ritardi iniziali e successivi variabili e tenere premuti due tasti contemporaneamente causerà la ripetizione di uno solo di essi.

È necessario tenere un registro di ciascun tasto attualmente premuto e ignorare gli eventi keydown quando la chiave è già inattiva. Ciò è dovuto al fatto che molti browser generano un evento keydown e un evento keypress quando si verifica una ripetizione automatica, e se si sta riproducendo la ripetizione della chiave, è necessario eliminarla.

Ad esempio:

// Keyboard input with customisable repeat (set to 0 for no key repeat) 
// 
function KeyboardController(keys, repeat) { 
    // Lookup of key codes to timer ID, or null for no repeat 
    // 
    var timers= {}; 

    // When key is pressed and we don't already think it's pressed, call the 
    // key action callback and set a timer to generate another one after a delay 
    // 
    document.onkeydown= function(event) { 
     var key= (event || window.event).keyCode; 
     if (!(key in keys)) 
      return true; 
     if (!(key in timers)) { 
      timers[key]= null; 
      keys[key](); 
      if (repeat!==0) 
       timers[key]= setInterval(keys[key], repeat); 
     } 
     return false; 
    }; 

    // Cancel timeout and mark key as released on keyup 
    // 
    document.onkeyup= function(event) { 
     var key= (event || window.event).keyCode; 
     if (key in timers) { 
      if (timers[key]!==null) 
       clearInterval(timers[key]); 
      delete timers[key]; 
     } 
    }; 

    // When window is unfocused we may not get key events. To prevent this 
    // causing a key to 'get stuck down', cancel all held keys 
    // 
    window.onblur= function() { 
     for (key in timers) 
      if (timers[key]!==null) 
       clearInterval(timers[key]); 
     timers= {}; 
    }; 
}; 

quindi:

// Arrow key movement. Repeat key five times a second 
// 
KeyboardController({ 
    37: function() { Move(-1, 0); }, 
    38: function() { Move(0, -1); }, 
    39: function() { Move(1, 0); }, 
    40: function() { Move(0, 1); } 
}, 200); 

Sebbene, molti giochi basati sull'azione hanno un tempo fisso ciclo telaio principale, che si può legare il tasto su/giù movimentazione in .

+0

sì, Ive ha provato a risolvere il problema in questo modo: ma non sparisce affatto – alex

+0

^^^^^^ ottima soluzione, davvero benchè fuori, e un gioco da ragazzi per integrarsi :) – chim

1

Poiché questo evento è quello di spostare whatever da una posizione a una posizione, perché non si usa onkeypress evento, quindi in questo modo se la chiave utente preme il tasto up, il whatever continuerà a muoversi verso l'alto, come il Pressed(e) sarà chiamato molte volte fino a quando l'utente non rilascerà la chiave.

<body onLoad="Load()" onkeypress="Pressed(event)"> 
+0

stesso problema. il ritardo di 1 secondo è ancora lì, e quando vengono premuti due tasti, riconosce solo 1 di essi. – alex

2

È possibile avviare il movimento onkeydown e terminarlo solo sukeyup?

4

ho risolto in questo modo:

 
var pressedl = 0; 
var pressedu = 0; 
var pressedr = 0; 
var pressedd = 0; 

function Down(e) { 
     cxc = e.keyCode; 
     if(cxc == 37) 
      pressedl = 1; 
     if(cxc == 38) 
      pressedu = 1; 
     if(cxc == 39) 
      pressedr = 1; 
     if(cxc == 40) 
      pressedd = 1; 
     //alert(cxc); 
    } 
    function Up(e) { 
     cxc = e.keyCode; 
     if(cxc == 37) 
      pressedl = 0; 
     if(cxc == 38) 
      pressedu = 0; 
     if(cxc == 39) 
      pressedr = 0; 
     if(cxc == 40) 
      pressedd = 0; 
     //alert(cxc); 
    } 

<body onLoad="Load()" onKeyDown="Down(event)" onKeyUp="Up(event)">

+3

Grazie a Bobince per avermi indicato nella giusta direzione! – alex

1

Sono un principiante assoluto in questo, ma perché non combinare KeyDown con KeyUp? Sto lavorando a un progetto simile in questo momento e, dopo aver controllato quirksmode, ho intenzione di esporre a capire come combinare i due eventi in modo tale che l'intero intervallo tra Down e Up realizzi l'effetto desiderato.

+0

Questo è troppo lavoro, se la soluzione è così semplice. Basta usare il codice dalla risposta accettata – alex

1

Questa è quasi la stessa come la risposta eccellente da @bobince

ho modificato leggermente per consentire i valori individuali per l'intervallo

// Keyboard input with customisable repeat (set to 0 for no key repeat) 
// usage 
/** 
KeyboardController({ 
    32: {interval:0, callback: startGame }, 
    37: {interval:10, callback: function() { padSpeed -= 5; } }, 
    39: {interval:10, callback: function() { padSpeed += 5; } } 
}); 
*/ 

function KeyboardController(keyset) { 
    // Lookup of key codes to timer ID, or null for no repeat 
    // 
    var timers= {}; 

    // When key is pressed and we don't already think it's pressed, call the 
    // key action callback and set a timer to generate another one after a delay 
    // 
    document.onkeydown= function(event) { 
     var key= (event || window.event).keyCode; 
     if (!(key in keyset)) 
      return true; 
     if (!(key in timers)) { 
      timers[key]= null; 
      keyset[key].callback(); 
      if (keyset[key].interval !== 0) 
       timers[key]= setInterval(keyset[key].callback, keyset[key].interval); 
     } 
     return false; 
    }; 

    // Cancel timeout and mark key as released on keyup 
    // 
    document.onkeyup= function(event) { 
     var key= (event || window.event).keyCode; 
     if (key in timers) { 
      if (timers[key]!==null) 
       clearInterval(timers[key]); 
      delete timers[key]; 
     } 
    }; 

    // When window is unfocused we may not get key events. To prevent this 
    // causing a key to 'get stuck down', cancel all held keys 
    // 
    window.onblur= function() { 
     for (key in timers) 
      if (timers[key]!==null) 
       clearInterval(timers[key]); 
     timers= {}; 
    }; 
}; 

Ho anche avuto un piano per usare setTimeout invece di setInterval per i motivi indicati in questa domanda: setTimeout or setInterval?

Aggiornerò questa risposta una volta che ho modificato e testato.