2010-09-11 4 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. будет ждать ответов. –

+0

хорошо, он работает на деле, но не так, как ожидалось. Моя игра - таймерная игра, и пауза в 1 сек, ожидая повторных нажатий клавиш, не очень хороша. Это расстраивает. – alex

+0

Почему вы не пытаетесь использовать флэш-подход. прозрачный flash swf, который захватывает события, а затем соответственно вызывает JS. http://www.java2s.com/Code/Flash-Flex-ActionScript/Development/UpLeftSensor.htm –

ответ

27

Если вы хотите повторить ключ в контролируемым образом, вы должны реализовать его самостоятельно, так как события нажатия клавиш увольняют зависит от идеи ОС о том, как ключи должны повторяться. Это означает, что могут быть переменные начальные и последующие задержки, и одновременное удерживание двух клавиш вызовет только одно из них.

Вам нужно будет сохранить запись о том, нажата ли каждая клавиша и проигнорировать события keydown, когда ключ уже выключен. Это связано с тем, что многие браузеры будут запускать keydown, а также событие 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

Да, Ive попытался исправить это следующим образом: но он вообще не срабатывает – alex

+0

^^^^^^ отличное решение, действительно хорошо, хотя и для того, чтобы интегрировать :) – chim

1

Как это событие, чтобы переместить whatever из одного положения в одной позиции, то почему бы вам не использовать onkeypress события, так что в этом пути, если ключ пользователя нажал клавишу up, то whatever будет продолжать двигаться вверх, как Pressed(e) будет вызываться много раз, пока пользователь не выпустит ключ.

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

такой же проблема. задержка в 1 секунду все еще существует, и когда нажаты две клавиши, она распознает только 1 из них. – alex

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

1

Это здесь Лукас решения в более абстрактной версии:

http://jsfiddle.net/V2JeN/4/

Кажется, вы можете только нажать 3 ключа за раз, к моему удивлению.

1

Я новичок в этом, но почему бы не комбинировать KeyDown с KeyUp? Сейчас я работаю над подобным проектом, и после проверки quirksmode я собираюсь изложить, как объединить два события таким образом, чтобы все время между Down и Up осуществляло желаемый аффект.

+0

Thats way too much work, если решение так просто. Просто используйте код из принятого ответа – alex

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?

Я буду обновлять этот ответ, как только я изменен и протестирована.

Смежные вопросы