supprimer la touche appuyez sur le délai en javascript

J'ai le problème suivant: J'essaie d'écrire un jeu javascript, et le personnage est contrôlé par les touches fléchées.
Le problème est, quand on maintient la touche enfoncée, il y a un court délai entre le déclenchement de la première pression de touche et le kepress répété.
En outre, lorsque l'on appuie sur la touche "Flèche droite" et la maintient enfoncée, puis appuie sur la touche "Flèche Haut", le personnage ne se déplace pas vers le coin supérieur droit, mais arrête le déplacement dans la bonne direction et commence à se déplacer jusqu'.
C'est le code que j'utilise:

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

Quelqu'un a une idée??

24
demandé sur alex 2010-09-11 19:01:08

7 réponses

Si vous voulez que la répétition des touches soit contrôlable, vous devrez l'implémenter vous-même, car les événements keypress sont déclenchés en fonction de l'idée du système d'exploitation de la répétition des touches. Cela signifie qu'il peut y avoir des retards initiaux et suivants variables, et en maintenant deux touches à la fois, une seule d'entre elles se répétera.

Vous devrez conserver un enregistrement indiquant si chaque touche est actuellement enfoncée et ignorer les événements keydown lorsque la touche est déjà enfoncée. C'est parce que de nombreux navigateurs déclencheront un keydown ainsi qu'un événement keypress lorsqu'un autorepeat se produit, et si vous reproduisez la répétition de la clé vous-même, vous devrez supprimer cela.

Par exemple:

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

Puis:

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

Bien que, la plupart des jeux basés sur l'action ont une boucle de trame principale à temps fixe, dans laquelle vous pouvez attacher la gestion de la clé Haut/Bas.

27
répondu bobince 2010-09-11 16:04:33

Je l'ai résolu comme ceci:

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)">

4
répondu alex 2010-09-11 16:23:05

Vous pourriez commencer le mouvement onkeydown et seulement le terminer onkeyup?

2
répondu ikanobori 2010-09-11 16:08:32

Comme cet événement doit déplacer whatever d'une position à une position, pourquoi n'utilisez-vous pas l'événement onkeypress, de sorte que si la touche utilisateur appuie sur la touche up, le whatever continuera à monter, car le Pressed(e) sera appelé plusieurs fois jusqu'à ce que l'utilisateur libère la clé.

<body onLoad="Load()" onkeypress="Pressed(event)">
1
répondu Garis M Suero 2010-09-11 15:13:33

Voici la solution de Lucas dans une version plus abstraite:

Http://jsfiddle.net/V2JeN/4/

Semble que vous ne pouvez appuyer que sur 3 touches à la fois à ma grande surprise.

1
répondu dirkk0 2011-01-12 18:55:11

Je suis un novice total à cela, mais pourquoi ne pas combiner KeyDown avec KeyUp? Je travaille sur un projet similaire en ce moment et, après avoir vérifié quirksmode je vais essayer de comprendre comment combiner les deux événements de sorte que tout le temps entre un bas et un haut réalise l'effet désiré.

1
répondu jtmengel 2011-06-19 21:24:32

C'est presque la même que l'excellente réponse de @bobince

Je l'ai légèrement modifié pour autoriser des valeurs individuelles pour l'intervalle

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

J'ai aussi un plan pour utiliser setTimeout au lieu de setInterval pour les raisons données dans cette question: setTimeout ou setInterval?

Je mettrai à jour cette réponse une fois que j'aurai modifié et testé.

1
répondu chim 2017-05-23 12:24:14