我正在用JavaScript重拍经典的蛇只是为了周末的乐趣,我遇到了这个问题,如果我按下按钮的速度很快 - 蛇(我的情况下是卡特彼勒)能够改变方向到对面然后碰到自己
重建这种情况的方法如下:
方向例如是'left'
按下(或向下)并在
之后快速按下现在毛毛虫倒退了。我的目标是它应该掉头
我对相反的目录进行了检查,但这并没有阻止这个
update = function() {
if (cat.direction != 'right' && key[37] === true) {
cat.direction = 'left';
}
if (cat.direction != 'left' && key[39] === true) {
cat.direction = 'right';
}
if (cat.direction != 'down' && key[38] === true) {
cat.direction = 'up';
}
if (cat.direction != 'up' && key[40] === true) {
cat.direction = 'down';
}
};
我使用普通的addEventListener
进行按键监听,但是我将其更改为另一种方法(在某处找到),我经常更新密钥,而且卡特彼勒移动只是偶尔发生,因为我认为直接关联绘图,改变方向和在同一时间间隔内移动可能是一个问题。我希望我能理解,如果不清楚,我很抱歉 - 如果有的话,我很乐意提供更多信息。
答案 0 :(得分:3)
一种解决方案是每次移动不会处理多个密钥,但为了提高响应速度,您可以实现密钥缓冲区,而不是像您所知的那样维护密钥状态。您只会在该缓冲区中收集箭头键按下,而不会将相同键的任何重复按入其中。
以下是对代码的相关更改:
初始化密钥缓冲区:
var keyBuffer = [];
按下时按箭头键进入缓冲区:
var keyDown = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
// *** Queue the arrow key presses
if (keyCode >= 37 && keyCode <= 40 &&
keyCode !== keyBuffer[keyBuffer.length-1] && ) {
keyBuffer.push(keyCode);
}
};
一次从缓冲区处理一个密钥:
var update = function() {
// *** Extract next key from buffer, and only treat that one
// -- could be `undefined`, but that is not a problem:
var key = keyBuffer.shift();
if(cat.direction != 'right' && key === 37){
cat.direction = 'left';
} else if(cat.direction != 'left' && key === 39){
cat.direction = 'right';
} else if(cat.direction != 'down' && key === 38){
cat.direction = 'up';
} else if(cat.direction != 'up' && key === 40){
cat.direction = 'down';
}
};
仅在移动时处理下一个键:
function loop() {
board.resetCanvas();
if(counter > 1000){
update(); // ***only process buffered keys when moving
cat.move();
counter = 0;
}
cat.draw();
counter += 5*cat.multiplier;
};
就是这样。请参阅下面的小提琴:
var canvas = document.getElementById("board");
var context = canvas.getContext("2d", {alpha:false});
var pieceSideLength = canvas.width / 40;
var key = [];
var keyBuffer = [];
window.addEventListener('keyup', function(e) {
this.keyUp.call(this, e);
}, false);
window.addEventListener('keydown', function(e) {
this.keyDown.call(this, e);
}, false);
function Piece(x,y){
this.x = x;
this.y = y;
}
board = {
leftBound: 0,
rightBound: canvas.width / pieceSideLength,
topBound: 0,
bottomBound: canvas.height / pieceSideLength,
drawPiece: function(x, y, color){
context.fillStyle = color;
context.fillRect(x*pieceSideLength,y*pieceSideLength,pieceSideLength,pieceSideLength);
context.strokeStyle = 'white';
context.strokeRect(x*pieceSideLength,y*pieceSideLength,pieceSideLength,pieceSideLength);
},
resetCanvas: function(){
context.clearRect(0,0,canvas.width,canvas.height);
}
};
//cat as for caterpillar
cat = {
x: canvas.width/pieceSideLength/2, //initial x
y: canvas.height/pieceSideLength/2, //initial y
pieces: [],
direction: 'up',
color: '#5da03c',
shouldGrow: false,
multiplier: 5,
init: function(){
cat.pieces.push(new Piece(this.x, this.y));
},
move: function(){
if(cat.pieces.length <= 10){
cat.shouldGrow = true;
}
var newX = cat.pieces[cat.pieces.length-1].x;
var newY = cat.pieces[cat.pieces.length-1].y;
if(cat.direction=='up'){
cat.makeNewHeadAt(newX,newY-1);
}
if(cat.direction=='down'){
cat.makeNewHeadAt(newX,newY+1);
}
if(cat.direction=='left'){
cat.makeNewHeadAt(newX-1,newY);
}
if(cat.direction=='right'){
cat.makeNewHeadAt(newX+1,newY);
}
cat.grow();
},
makeNewHeadAt: function(x,y){
cat.pieces.push(new Piece(x,y));
},
grow: function(){
if(cat.shouldGrow == false){
cat.pieces.shift();
} else {
cat.shouldGrow = false;
}
},
draw: function(){
for(i=0;i<cat.pieces.length;i++){
var p = cat.pieces[i];
board.drawPiece(p.x,p.y,cat.color);
}
}
};
cat.init();
update = function() {
// *** Extract next key from buffer, and only treat that one
// -- could be `undefined`, but that is not a problem:
var key = keyBuffer.shift();
if(cat.direction != 'right' && key === 37){
cat.direction = 'left';
} else if(cat.direction != 'left' && key === 39){
cat.direction = 'right';
} else if(cat.direction != 'down' && key === 38){
cat.direction = 'up';
} else if(cat.direction != 'up' && key === 40){
cat.direction = 'down';
}
};
keyUp = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
this.key[keyCode] = false;
};
keyDown = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
// *** Queue the key presses
if (keyCode >= 37 && keyCode <= 40 &&
keyCode !== keyBuffer[keyBuffer.length-1]) {
keyBuffer.push(keyCode);
}
this.key[keyCode] = true;
};
var counter = 0;
function loop() {
board.resetCanvas();
if(counter > 1000){
update(); // ***only process buffered keys when moving
cat.move();
counter = 0;
}
cat.draw();
counter += 5*cat.multiplier;
};
setInterval(loop, 1);
body { margin: 0px }
<div>
<canvas id="board" width="300" height="200" style="display: block; margin: 0 auto; background-color: #553300; border-style: solid; border-color: green;"></canvas>
</div>
您可以通过替换它来限制缓冲区大小:
keyBuffer.push(keyCode);
使用:
keyBuffer = keyBuffer.slice(-2).concat(keyCode);
这会将大小限制为3.根据需要调整slice
参数。
答案 1 :(得分:0)
你可以跟踪蛇是否已经移动了#39;如果您收到键盘输入,请不要对另一个按键做出反应,直到蛇移动为止。这样,您每次移动只允许使用1个键,因此您无法改变方向并遇到自己。
修改示例:link
user type
等等