我正在从事蛇游戏项目(针对JavaScript课程)。 我试图避免出现“错误”,即当同时使用两个键时,游戏会认为存在碰撞,而在视觉上则没有碰撞。
键盘键管理代码
document.onkeydown = function handleKeyDown(e){
const key = e.keyCode;
let newDirection;
switch(key){
case 37:
newDirection = "left";
break;
case 38:
newDirection = "up";
break;
case 39:
newDirection = "right";
break;
case 40:
newDirection = "down";
break;
case 32:
restart();
return;
default:
return;
}
snakee.setDirection(newDirection);
}
如何避免这种情况? 有人告诉我了preventDefault()事件,我应该使用它吗?
EDIT1
这是我的蛇构造函数的一部分的checkCollision方法:
this.checkCollision = function(){
let wallCollision = false;
let snakeCollision = false;
const head = this.body[0];
const rest = this.body.slice(1);
const snakeX = head[0];
const snakeY = head[1];
const minX = 0;
const minY = 0;
const maxX = widthInBlocks-1;
const maxY = heightInBlocks-1;
const isNotBetweenHorizontalWalls = snakeX < minX || snakeX > maxX;
const isNotBetweenVerticalWalls = snakeY < minY || snakeY > maxY;
if(isNotBetweenHorizontalWalls || isNotBetweenVerticalWalls){
wallCollision = true;
}
for(let i = 0;i < rest.length;i++){
if(snakeX == rest[i][0] && snakeY == rest[i][1]){
snakeCollision = true;
}
}
return wallCollision || snakeCollision;
};
EDIT2:
因此,在您回答完之后,这里是使用的解决方案。
我以前使用过switch
,我决定改用if/else
。
const map = {};
onkeydown = onkeyup = function(e){
e = e || event;
map[e.keyCode] = e.type == 'keydown';
let newDirection;
if(map[37]){
newDirection = "left";
} else if(map[38]){
newDirection = "up";
} else if(map[39]){
newDirection = "right";
} else if(map[40]){
newDirection = "down";
} else if(map[32]){
restart();
}
snakee.setDirection(newDirection);
}
但,如果地图对象的所有属性都为假,那么问题仍然存在,当我同时按下两个键时会发生这种情况。
Object {
32: false,
37: false,
38: false,
39: false,
40: false
}
我不知道如何防止这种情况。
答案 0 :(得分:1)
碰撞是什么意思? onkeydown
事件将仅返回按下键盘上的最后一个键,即使按住多个键也是如此。
如果先按down
再按left
,则onkeydown
事件将返回left
键的键码。
您不需要使用event.preventDefault()
,因为这将停止寻找键按下键,而不会返回任何内容。
您的代码应该可以与我所看到的正常工作。
如果要检测多个击键,则应为此保留一个地图对象。
const keysPressed = {};
onkeydown = function(e) => {
const e = e || event;
keyPressed[e.keyCode] = e.keyCode >= 37 && e.keyCode <= 40;
// move your snake now with the keys pressed
}
答案 1 :(得分:1)
这是游戏构建中的一个众所周知的问题,最好的方法是通过对操作进行排队。这可能是通过标志或实际队列。按键时,将记录用户操作或将其添加到列表中并执行。
您的游戏循环负责在适当的时间检查标志或输入队列,并相应地更新游戏状态。
以下教程将提供一些有关如何实现和更新基本输入状态的见解:https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls
答案 2 :(得分:1)
请查看at this example,了解如何处理同时击键。
在结果屏幕上单击,打开控制台,然后按top +向左或向右,您将看到自定义console.log到每个:)
var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
e = e || event; // to deal with IE
map[e.keyCode] = e.type == 'keydown';
/* insert conditional here */
console.log(map);
if(map[38] && map[39]) {
console.log('Moved Top & Right!')
}
if(map[38] && map[37]) {
console.log('Moved Top & Left!')
}
}
window.addEventListener('keydown', onkeyup);
window.addEventListener('keyup', onkeydown);
基于以下问题的示例:How to detect if multiple keys are pressed at once using JavaScript?
答案 3 :(得分:0)
您应该使用onkeyup事件代替onkeydown事件,它将解决您的碰撞问题。