我正在用JavaScript制作游戏,其中玩家是由箭头键控制的。
如果用户按下箭头键并同时更改选项卡,则当他们返回到选项卡时,由于事件监听器触发keydown
而未通知keyup
,因此播放器仍在移动。用户已更改标签。
在用户切换标签并返回后,我如何能够停止触发事件?
换句话说,我如何确保在用户切换选项卡并返回后,播放器不会根据先前按住的箭头键移动?
这里是我用来说明问题的示例:https://jsfiddle.net/mgh38d1e/
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var player = {x: 0, y: 0};
function loop() {
// draw background
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// draw player
ctx.fillStyle = 'lawngreen';
ctx.fillRect(player.x, player.y, 50, 50);
if(right) player.x += 1;
requestAnimationFrame(loop);
}
loop();
var right = false;
addEventListener('keydown', function(e) {
if(e.key == 'd')
right = true;
});
addEventListener('keyup', function(e) {
if(e.key == 'd')
right = false;
});
<h1>Press D to move right</h1>
<canvas id="game" width="600" height="300"></canvas>
答案 0 :(得分:1)
这就是我要记住的事情。
function byId(id) {
return document.getElementById(id)
}
function newEl(tag) {
return document.createElement(tag)
}
function qsa(sel, par = document) {
return par.querySelectorAll(sel)
}
window.addEventListener('load', onLoaded, false);
class kbKey {
constructor(name, keyCode) {
this.name = name;
this.keyCode = keyCode;
return this;
}
}
var keys = [];
var arrowKeys = [
[null, new kbKey('^', 38), null],
[new kbKey('<', 37), new kbKey('V', 40), new kbKey('>', 39), ]
];
var numPad = [
[new kbKey('7', 103), new kbKey('8', 104), new kbKey('9', 105)],
[new kbKey('4', 100), new kbKey('5', 101), new kbKey('6', 102)],
[new kbKey('1', 97), new kbKey('2', 98), new kbKey('3', 99)],
[new kbKey('>', 39), new kbKey('0', 96), new kbKey('.', 110)]
];
function onLoaded(evt) {
window.addEventListener('keydown', onkeydown, false);
window.addEventListener('keyup', onkeyup, false);
window.addEventListener('focus', onFocus, false);
window.addEventListener('blur', onBlur, false);
keys = keys.fill(false);
drawKeys(numPad);
}
function onkeydown(evt) {
keys[evt.keyCode] = true;
// console.log(evt.key, evt.which);
updateDisplay();
}
function onkeyup(evt) {
keys[evt.keyCode] = false;
updateDisplay();
}
function onBlur(evt) {
keys = keys.fill(false);
}
function onFocus(evt) {
updateDisplay();
}
function updateDisplay() {
let cells = Array.from(qsa('#keyboard td'));
cells.forEach(
function(cell, index, collection) {
if (cell.dataset.code != undefined) {
if (keys[parseInt(cell.dataset.code)] == true)
cell.classList.add('active');
else
cell.classList.remove('active');
}
}
);
}
function drawKeys(keydata2D) {
let tbl = byId('keyboard');
keydata2D.forEach(function(rowArray, rowIndex, rowCollection) {
let tr = newEl('tr');
rowArray.forEach(
function(key, col, keyArray) {
let td = newEl('td');
tr.appendChild(td);
if (key != null) {
td.textContent = key.name;
td.dataset.code = key.keyCode;
}
}
);
tbl.appendChild(tr);
});
}
td[data-code] {
border: solid 1px gray;
}
.active {
background-color: #ffad68;
}
<table id='keyboard'></table>