javascript - 将按键模拟为 keydown 和 keyup
问题描述
我构建了一个游戏并遇到了问题。我的游戏寻找一些可以移动角色的按键。我添加了一个 A* 算法,让玩家可以选择通过鼠标点击来移动他们的角色(它提供了目标点的键)。
我的问题是:代码正在寻找允许连续单击的 keydown 并且算法返回目标点的键,该键应该是按键作为每个键。
我应该如何为此模拟按键?(主要问题在 AStarWalk 功能中)
代码:
class Event {
constructor(engine) {
this.engine = engine;
this.engine.event = this;
this.focus = false;
this.pressedKeys = {};
this.events = {};
// - - - - - - - - - -
// Events
this.onKey('keydown', 'gameWindow', ['KeyA', 'ArrowLeft'], () => {
this.engine.player.movePlayer(1);
}); // Left
this.onKey('keydown', 'gameWindow', ['KeyW', 'ArrowUp'], () => {
this.engine.player.movePlayer(3);
}); // Up
this.onKey('keydown', 'gameWindow', ['KeyD', 'ArrowRight'], () => {
this.engine.player.movePlayer(2);
}); // Right
this.onKey('keydown', 'gameWindow', ['KeyS', 'ArrowDown'], () => {
this.engine.player.movePlayer(0);
}); // Down
this.onKey('keydown', 'gameWindow', ['KeyR'], () => {
this.engine.player.running = true;
}); // Start running
this.onKey('keyup', 'gameWindow', ['KeyR'], () => {
this.engine.player.running = false;
}); // Stop running
this.onKey('keyup', 'gameWindow', ['PrintScreen'], () => {
console.log('save a picture');
});
this.onKey('focus', 'gameWindow', () => {
this.focus = true;
}); // On focus the game
this.onKey('focusout', 'gameWindow', () => {
this.focus = false;
this.pressedKeys = {};
}); // Focus has out from game
this.onKey('mousedown','gameWindow', [0], (e) => {
let x = Math.floor(e.layerX / this.engine.mapSettings.pxPerSquare);
let y = Math.floor(e.layerY / this.engine.mapSettings.pxPerSquare);
let node = [x, y];
let path = this.engine.astar.findPath(node);
this.AStarWalk(path);
});
// - - - - - - - - - -
// addEventListener
// code - for keyboard
// botton - for mouse
for (let id in this.events) {
for (let type in this.events[id]) {
if (!this.events[id].hasOwnProperty(type))
continue;
document.getElementById(id).addEventListener(type, (event) => {
let e = event;
if (this.inArray(type, ['keydown', 'keyup']))
event.preventDefault();
// Define variables
let key = e.code || e.button; // e.keyCode || e.which;
// Check if the key has event
if (!this.events[id][type].hasOwnProperty(key) && !this.events[id]['keyup'].hasOwnProperty(key))
return;
// Check if the key already pressed
if (this.pressedKeys.hasOwnProperty(key) && type === 'keydown')
return;
// Do
if (type === 'keydown')
this.pressedKeys[key] = e;
else if (type === 'keyup') {
this.runCallbacks(this.events[id][type][key]);
}
else if (this.inArray(type, ['focus', 'focusout'])) {
for (let callback in this.events[id][type]) {
if (!this.events[id][type].hasOwnProperty(callback))
continue;
this.events[id][type][callback](e);
}
}
else if (this.inArray(type, ['mousedown', 'mouseup'])) {
this.runCallbacks(this.events[id][type][key], e);
}
});
document.getElementById(id).addEventListener('contextmenu', (e) => {
e.preventDefault();
});
}
}
// - - - - - - - - - -
// Thread
this.engine.thread.thread(true, 0, (1000 / this.engine.graphic.lastfps), () => {
for (let id in this.events) {
for (let key in this.pressedKeys) {
this.runCallbacks(this.events[id].keydown[key], key);
}
}
});
}
runCallbacks(array, key) {
let e;
for (let callback in array) {
if (!array.hasOwnProperty(callback))
continue;
e = (this.pressedKeys[key] instanceof Event) ? this.pressedKeys[key] : key;
array[callback](e);
}
}
inArray(key, array) {
for (let i in array)
if (array.hasOwnProperty(i) && array[i] === key)
return true;
return false;
}
onKey() {
let event = arguments[0];
let id = arguments[1];
let keyCode = (this.inArray(event, ['keydown', 'keyup', 'mousedown', 'mouseup'])) ? arguments[2] : null;
let callback = (!this.inArray(event, ['keydown', 'keyup', 'mousedown', 'mouseup'])) ? arguments[2] : arguments[3];
// Convert keyCodeList to an array based on keyCode.
if (keyCode != null) {
if (!keyCode instanceof Array)
keyCode = [keyCode];
}
// Create event id if is not exist.
if (!this.events.hasOwnProperty(id)) {
this.events[id] = {
keydown: {},
keyup: {},
focus: [],
focusout: [],
mousedown: {},
mouseup: {}
};
}
// Add event to an array
if (keyCode !== null) {
let done = false;
for (let k in keyCode) {
if (!keyCode.hasOwnProperty(k))
continue;
k = keyCode[k].toString();
for (let key in this.events[id][event]) {
if (key === k) {
if (callback !== undefined)
this.events[id][event][k].push(callback);
if (event === 'keydown')
this.events[id]['keyup'][k].push(() => { delete this.pressedKeys[k]; });
done = true;
break;
}
}
if (!done) {
if (callback !== undefined)
this.events[id][event][k] = [callback];
if (event === 'keydown')
this.events[id]['keyup'][k] = [() => { delete this.pressedKeys[k]; }];
}
}
}
else {
this.events[id][event].push(callback);
}
}
AStarGetKey(state) {
if (state === 'LEFT') return 'ArrowLeft';
if (state === 'UP') return 'ArrowUp';
if (state === 'RIGHT') return 'ArrowRight';
if (state === 'DOWN') return 'ArrowDown';
if (state === 'LEFTUP') return ['ArrowLeft', 'ArrowUp'];
if (state === 'LEFTDOWN') return ['ArrowLeft', 'ArrowDown'];
if (state === 'RIGHTUP') return ['ArrowRight', 'ArrowUp'];
if (state === 'RIGHTDOWN') return ['ArrowRight', 'ArrowDown'];
return false;
}
AStarWalk(path) {
for (let i in path) {
let key = this.AStarGetKey(path[i]);
if (!key) break;
// How to simulate the keypress per key which works with keydown ?
document.getElementById('gameWindow').dispatchEvent(new KeyboardEvent('keypress',{'code': key}));
}
}
}
对不起我的英语家伙,不是我的母语。我希望你能找到理解我的力量;-)
解决方案
推荐阅读
- circleci - CircleCI 配置错误 - 作业可能是对另一个作业的字符串引用
- python-3.x - 会话图为空。在调用 run() 之前向图中添加操作。[tf2]
- c# - 打开 PDF 文件,在任何 subfolder_filename 中是一个数字(用户知道)+ _v + 数字形式 1.999
- reactjs - ReactNode 中缺少历史定义
- python - Pandas 尽可能将混合类型的列值转换为数字
- angular - 如何为用户登录数据创建存根数据
- python - 使用多线程时如何正确处理此错误
- javascript - 如何在Angular中用空项目填充数组
- c# - Editorconfig:如何获取所有使用 `public` 的警告
- html - 如何在 Vue 中通过 v-for 生成列表