javascript - 在 setInterval 中使用 setTimeout 会导致对象移动速度出现不必要的增加

标签 javascript

我正在测试我正在做的练习游戏的运动,我正在尝试使用一个循环,该循环将在一个间隔内运行两次(因为该对象是一只兔子),以便该对象不会连续循环移动,并且具有唯一性。我的执行方式是间隔每 1500 毫秒运行一次,超时(在间隔内)将运行该时间的一半,以创建兔子向一个方向移动两次而不是一次。问题是,过了一段时间,兔子会向前迈出更大的步子,而且速度更快。我不完全确定问题是什么,感谢您查看此内容。这是我的代码

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var wabbits = {
  wabbit1: {
    x: 200,
    y: 200,
    w: 10,
    h: 10,
    speed: 2,
    moving: "",
    dead: false,
    updateInterval: 2000
  }
};
  //make it easier to type out the object
  var bunny = wabbits.wabbit1;

var movement = ["up", "down", "left", "right"];
var left = "left";
var up = "up";
var down = "down";
var right = "right";

var update = setInterval(function(){
  draw();
}, 1);

canvas.style.backgroundColor = "green";

function draw(){
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = "grey";
  context.fillRect(bunny.x, bunny.y, bunny.w, bunny.h);
  context.fill();
  border();
}

function border(){
  if(bunny.x <= 0){
    bunny.x += bunny.speed * 2;
  }
  if(bunny.x >= 490){
    bunny.x -= bunny.speed * 2;
  }
  if(bunny.y <= 0){
    bunny.y += bunny.speed * 2;
  }
  if(bunny.y >= 490){
    bunny.y -= bunny.speed * 2;
  }
}

function bunny1move(){
	if(!wabbits.wabbit1.dead){
		var randM = Math.floor(Math.random() * 3) + 0;
		wabbits.wabbit1.moving = movement[randM];
		function mv(){
			switch(wabbits.wabbit1.moving){
				case "up":
					wabbits.wabbit1.y -= wabbits.wabbit1.speed;
				break;
				case "down":
					wabbits.wabbit1.y += wabbits.wabbit1.speed;
				break;
				case "left":
					wabbits.wabbit1.x -= wabbits.wabbit1.speed;
				break;
				case "right":
					wabbits.wabbit1.x += wabbits.wabbit1.speed;
				break;
				default: 
					console.log("something in bunny1.mv() is not working properly, err: " + wabbits.wabbits1.moving);
				break;
			};
			if(wabbits.wabbit1.y <= 0){
				wabbits.wabbit1.y += wabbits.wabbit1.speed * 2;
				wabbits.wabbit1.moving = down;
			}
			if(wabbits.wabbit1.y >= 758){
				wabbits.wabbit1.y -= wabbits.wabbit1.speed * 2;
				wabbits.wabbit1.moving = up;
			}
			if(wabbits.wabbit1.x <= 0){
				wabbits.wabbit1.x += wabbits.wabbit1.speed * 2;
				wabbits.wabbit1.moving = right;
			}
			if(wabbits.wabbit1.x >= 1356){
				wabbits.wabbit1.x -= wabbits.wabbit1.speed * 2;
				wabbits.wabbit1.moving = left;
			}
      //make mv repeat twice
			this.setTimeout(mv, wabbits.wabbit1.updateInterval / 2);
		}
		mv();
		
	}
}
//update the movement function
setInterval(bunny1move, wabbits.wabbit1.updateInterval);
<canvas id="canvas" height="500px" width="500px"></canvas>

最佳答案

在bunny1move中创建mv后,您立即调用它,但每次调用mv后,它都会设置一个超时,在一秒后再次调用自身。再次调用它后,它会设置一个新的超时,以便在下一秒后调用自己,依此类推。这个调用链无限延伸。

这本身并不算太糟糕,实际上这似乎就是你想要的,每秒都调用 mv 。当您每两秒调用一次 bunny1move 时,就会出现问题,每次重复调用 bunny1move 都会创建一个新的 mv 链,并且它们都堆叠在之前的链之上。

所以,并不是说兔子在每次迭代中移动得更远,而是越来越多的 mv 链被创建,并且它们都被同步调用,使得它看起来像是一个更长的跳跃,而实际上它只是很多更多小跳跃。

如果您将 console.log 语句放在 mv 末尾,您可以看到 mv 调用随着时间的推移而增加。

您应该能够完全摆脱 mv,然后每秒对 bunny1move 调用 setInterval:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var wabbits = {
  wabbit1: {
    x: 200,
    y: 200,
    w: 10,
    h: 10,
    speed: 2,
    moving: "",
    dead: false,
    updateInterval: 2000
  }
};
  //make it easier to type out the object
  var bunny = wabbits.wabbit1;

var movement = ["up", "down", "left", "right"];
var left = "left";
var up = "up";
var down = "down";
var right = "right";

var update = setInterval(function(){
  draw();
}, 1);

canvas.style.backgroundColor = "green";

function draw(){
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = "grey";
  context.fillRect(bunny.x, bunny.y, bunny.w, bunny.h);
  context.fill();
  border();
}

function border(){
  if(bunny.x <= 0){
    bunny.x += bunny.speed * 2;
  }
  if(bunny.x >= 490){
    bunny.x -= bunny.speed * 2;
  }
  if(bunny.y <= 0){
    bunny.y += bunny.speed * 2;
  }
  if(bunny.y >= 490){
    bunny.y -= bunny.speed * 2;
  }
}

function bunny1move(){
	if(!wabbits.wabbit1.dead){
		var randM = Math.floor(Math.random() * 3) + 0;
		wabbits.wabbit1.moving = movement[randM];
		switch(wabbits.wabbit1.moving){
			case "up":
				wabbits.wabbit1.y -= wabbits.wabbit1.speed;
			break;
			case "down":
				wabbits.wabbit1.y += wabbits.wabbit1.speed;
			break;
			case "left":
				wabbits.wabbit1.x -= wabbits.wabbit1.speed;
			break;
			case "right":
				wabbits.wabbit1.x += wabbits.wabbit1.speed;
			break;
			default: 
				console.log("something in bunny1.mv() is not working properly, err: " + wabbits.wabbits1.moving);
				break;
		};
		if(wabbits.wabbit1.y <= 0){
			wabbits.wabbit1.y += wabbits.wabbit1.speed * 2;
			wabbits.wabbit1.moving = down;
		}
		if(wabbits.wabbit1.y >= 758){
			wabbits.wabbit1.y -= wabbits.wabbit1.speed * 2;
			wabbits.wabbit1.moving = up;
		}
		if(wabbits.wabbit1.x <= 0){
			wabbits.wabbit1.x += wabbits.wabbit1.speed * 2;
			wabbits.wabbit1.moving = right;
		}
		if(wabbits.wabbit1.x >= 1356){
			wabbits.wabbit1.x -= wabbits.wabbit1.speed * 2;
			wabbits.wabbit1.moving = left;
		}
	}
}
//update the movement function
setInterval(bunny1move, wabbits.wabbit1.updateInterval / 2);
<canvas id="canvas" height="500px" width="500px"></canvas>

顺便说一句,您应该考虑将其发布到 https://codereview.stackexchange.com/ 。他们应该对设计程序的更好方法提出一些建设性意见,以提高灵 active 、可扩展性、可读性等。

关于javascript - 在 setInterval 中使用 setTimeout 会导致对象移动速度出现不必要的增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44608966/

相关文章:

javascript - Bootstrap 选项卡导航不起作用

用于删除特殊字符 []{}<> 的 JavaScript 代码

php - cometd 和 PHP : How to use Comet with a PHP Chat System?

javascript - 如何从 forEach 返回一个值

javascript - 如何将 javascript 数组绑定(bind)到 HTML,同时允许在数组中添加和删除?

javascript - 是否可以在将文件发送到服务器之前使用 javascript 将文件上传到内存中进行处理?

javascript - HTML - 用视频替换 div(图像和按钮)(仅当我按下按钮时)

javascript - 数据表自定义过滤

javascript - 我可以检查后台运行的应用程序是否 react 原生

javascript - 为什么 Angular.element/jqlite 找不到顶级元素?