Ich mache ein Web-Spiel und möchte einen Timer aufrufen, wenn der Benutzer das Spiel startet. Wenn ich eine der WASD-Tasten drücke, starten Sie den Timer. Das Problem ist, wenn Sie die Tasten mehr als einmal drücken, wird der Timer jedes Mal gestartet. Ich möchte die Funktion nur einmal aufrufen. Ich habe über clearInterval() nachgedacht, aber das würde den Timer stoppen. Nicht ideal.

Hier ist mein Code. (Geigenlink unten)

Ich denke, wenn eine Taste gedrückt wird, wird zuerst geprüft, ob fired gleich false ist. Wenn dies der Fall ist, setzen Sie es auf true. Wenn dann die Taste W, A, S oder D gedrückt wird, starten Sie den Timer.

Wenn der Schlüssel wieder hochkommt, setzen Sie fired erneut auf false.

var fired = false;
var timer = document.getElementById("timer");

var playerObj = {
    elapsedTime: 0,
    startTimer: function () {
        setInterval(function () {
            playerObj.elapsedTime += 1;
            timer.innerHTML = playerObj.elapsedTime;
        }, 1000);
    }
};

var fired = false;
document.onkeydown = function (e) {
    var w = e.keyCode == '87',
        a = e.keyCode == '65',
        s = e.keyCode == '83',
        d = e.keyCode == '68';
    if (!fired) {
        fired = true;
        if (w || a || s || d) {
           playerObj.startTimer();
        }
    }
};

document.onkeyup = function () {
     fired = false;
};

Ich habe auf die Antwort dieser Frage verwiesen und versucht, eine Flagge zu verwenden, aber dies ist nicht der Fall scheint den Trick nicht zu tun.

Geige

0
Matthew 22 Aug. 2015 im 05:28

4 Antworten

Beste Antwort

Die Schlüsselidee ist, den Timer nur zu starten, wenn fired false ist. Wenn der Timer einmal pro Spiel gestartet werden soll, setzen Sie fired beim ersten Keydown-Ereignis auf true und starten Sie den Timer. Überprüfen Sie bei nachfolgenden Keydown-Ereignissen den Wert von fired und lehnen Sie es ab, den Timer zu starten.

var fired = false;
var timer = document.getElementById("timer");

var playerObj = {
    elapsedTime: -1,
    update: function () {
      playerObj.elapsedTime += 1;
      timer.innerHTML = playerObj.elapsedTime;
    },
    startTimer: function () {
        playerObj.update();
        setInterval(playerObj.update, 1000);
    }
};

document.onkeydown = function (e) {
    var w = e.keyCode == '87',
        a = e.keyCode == '65',
        s = e.keyCode == '83',
        d = e.keyCode == '68';
    if (!fired) {
        fired = true;
        if (w || a || s || d) {
           playerObj.startTimer();
        }
    }
};
#timer {
  font-family: sans-serif;
  font-size: 24px;
  color: #444;
  border: 1px solid #ddd;
  display: inline-block;
  padding: 5px 15px;
}
<div id="timer">-</div>

Ein anderer Ansatz besteht darin, den Keydown-Handler nach dem ersten Keydown-Ereignis zu ersetzen.

var fired = false;
var timer = document.getElementById("timer");

var playerObj = {
    elapsedTime: -1,
    update: function () {
      playerObj.elapsedTime += 1;
      timer.innerHTML = playerObj.elapsedTime;
    },
    startTimer: function () {
        playerObj.update();
        setInterval(playerObj.update, 1000);
    }
};

var keyToString = {
  87: '&uarr;',
  65: '&larr;',
  83: '&darr;',
  68: '&rarr;'
};

function keyHandler(event) {             // Handles all valid keys.
  var display = document.getElementById('display');
  display.innerHTML = keyToString[event.keyCode];
}

document.onkeydown = function (event) {  // Handles the first valid key.
  if (keyToString[event.keyCode] !== undefined) {
    playerObj.startTimer();              // Start the timer.
    document.onkeydown = keyHandler;     // Replace this key handler.
    keyHandler(event);                   // Call the general key handler.
  }
};
#timer, #display {
  font-family: sans-serif;
  font-size: 24px;
  color: #444;
  padding: 5px 15px;
}
#timer {
  display: inline-block;
  border: 1px solid #ddd;
}
<div id="timer">-</div>

<div id="display"></div>
2
Michael Laszlo 22 Aug. 2015 im 03:50

Die Frage war ein wenig unklar, so dass dies möglicherweise die Marke verfehlt. Der Timer wird einmal pro WASD-Klick gestartet.

var timer = document.getElementById("timer");

var playerObj = {
    elapsedTime: 0,
    startTimer: function () {
        setInterval(function () {
            playerObj.elapsedTime += 1;
            timer.innerHTML = playerObj.elapsedTime;
        }, 1000);
    }
};

// keep track of keys indiividually
var keyPressed = {
    w: false,
    a: false,
    s: false,
    d: false
};

// make it easy to translate keyCodes to key names
var CODES = {
    87: 'w',
    65: 'a',
    83: 's',
    68: 'd'
};

document.onkeydown = function (e) {

    // look up the key
    var keyName = CODES[e.keyCode];

    // if it's one we're interested in and it hasn't been pressed yet
    if (keyName && !keyPressed[keyName]) {
        playerObj.startTimer();

        // mark it as having been pressed
        keyPressed[keyName] = true;
    }
};
0
reergymerej 22 Aug. 2015 im 02:54

Ich denke, Sie müssen Ihren Prozess ändern, um Folgendes zu tun:

Onkeydown Überprüfen Sie das Flag w / a / s / d, setzen Sie das Flag und starten Sie den Timer

onkeyup Wenn NICHT w / a / s / d-Tasten, setzen Sie das Flag auf false

Ist im Wesentlichen das, was Sie hier versuchen. Ich denke, das wird der Unterschied sein, also hör auf, wenn du / g / h / etc drückst.

0
Brian Mains 22 Aug. 2015 im 02:48

Sie benötigen dafür überhaupt kein Flag. Sie müssen lediglich den Ereignislistener nach dem Start des Timers auf null setzen. Diese Funktion wird dann nie wieder ausgeführt. Es ist besser als die anderen Lösungen hier, da diese Funktion nicht mehr ausgeführt werden soll und möglicherweise andere Ereignisse in der Benutzeroberfläche blockiert.

document.onkeydown = function (e) {
    var w = e.keyCode == '87',
        a = e.keyCode == '65',
        s = e.keyCode == '83',
        d = e.keyCode == '68';

    if (w || a || s || d) {
       playerObj.startTimer();
       document.onkeydown = null;
    }
};
1
skyline3000 22 Aug. 2015 im 02:58