2010-09-11 50 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?

我会更新这个答案,一旦我修改和测试。