2010-09-11 94 views
24

我有以下問題: 我正在嘗試編寫一個JavaScript遊戲,並且正在通過箭頭鍵控制該字符。
問題是,當按住鍵時,第一次按鍵和重複按鍵之間會有短暫的延遲。
此外,當按下「右箭頭鍵」並保持按下狀態,然後按下「上箭頭鍵」時,角色不會移動到右上角,而是停止向右移動並開始移動向上。
這是代碼我使用:在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); 
    } 

沒有任何人有一個想法?

+0

你的代碼不會工作,這是肯定的。我不確定你是否可以測試在JS中同時按下兩個鍵。將等待答案。 – 2010-09-11 15:02:54

+0

好吧,它確實在做事,但並不像預期的那樣。我的遊戲是一款基於計時器的遊戲,等待重複擊鍵並持續1秒就不好。這很令人沮喪。 – alex 2010-09-11 15:08:22

+0

爲什麼不嘗試使用基於閃存的方法。一個透明的閃存swf捕獲事件,然後相應地調用JS。 http://www.java2s.com/Code/Flash-Flex-ActionScript/Development/UpLeftSensor.htm – 2010-09-11 15:09:55

回答

27

如果你想在一個可控的方式鍵重複,你將不得不自己實現它,按鍵事件被觸發依賴於密鑰應該如何重複OS的想法。這意味着可能存在可變的初始延遲和延遲,並且一次按下兩個鍵將只導致其中一個重複。

您必須保存當前每個鍵是否被按下的記錄,並且在鍵已經關閉時忽略​​事件。這是因爲當發生自動重複時,許多瀏覽器會觸發​​以及keypress事件,並且如果您正在重現鍵重複自己,則需要禁止該事件。

例如:

// 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= {}; 
    }; 
}; 

則:

// 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); 

雖然,大多數基於動作的遊戲有一個固定的時間主框架循環,可以配合按鍵向上/向下處理成。

+0

是的,我試圖解決這個問題:但它根本不會觸發 – alex 2010-09-11 16:17:42

+0

^^^^^^優秀的解決方案,真的以及儘管出來,和一個整合:)一起收集 – chim 2012-11-26 14:10:13

1

作爲本次活動是從一個位置移動到whatever一個位置,你爲什麼不以這種方式使用onkeypress事件,因此如果用戶按下按鍵的up鍵,whatever將繼續向上移動,作爲Pressed(e)將被多次調用,直到用戶釋放密鑰。

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

同樣的問題。 1秒的延遲仍然存在,並且當兩個鍵被按下時,它只識別它們中的一個。 – alex 2010-09-11 15:26:02

2

你可以開始移動onkeydown並只結束onkeyup?

4

我已經解決了它這樣的:

 
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

感謝bobince指着我在正確的方向! – alex 2010-09-11 16:28:49

1

我是這個總的新手,但爲什麼不把KeyDown和KeyUp結合起來呢?我現在正在開展一個類似的項目,在查看了quirksmode之後,我將着手弄清楚如何將這兩個事件結合起來,以便在Down和Up之間的整個時間實現期望的影響。

+0

如果解決方法如此簡單,那就太麻煩了。只需使用接受答案中的代碼即可 – alex 2011-06-20 19:27:39

1

這是幾乎一樣從@bobince優秀的答案

我已經修改稍微允許的間隔

// 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= {}; 
    }; 
}; 

單個值,我也得到了使用的setTimeout計劃由於在這個問題給出的原因,而不是setInterval:setTimeout or setInterval?

我會更新這個答案,一旦我修改和測試。