防止蛇反向行进

时间:2017-03-26 17:17:41

标签: javascript

我正在用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';
    }
};

the full code

我使用普通的addEventListener进行按键监听,但是我将其更改为另一种方法(在某处找到),我经常更新密钥,而且卡特彼勒移动只是偶尔发生,因为我认为直接关联绘图,改变方向和在同一时间间隔内移动可能是一个问题。我希望我能理解,如果不清楚,我很抱歉 - 如果有的话,我很乐意提供更多信息。

2 个答案:

答案 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

等等