javascript 将物体沿直线匀速从 A 点移动到 B 点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13849185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Moving an object along a straight line at a constant speed from point A to B
提问by Jamie Rushworth
I know this has been asked a few times before, but there has been no answer that actually works that I can find. There is a similar one, but the speed varies depending on the distance travelled.
我知道这之前曾被问过几次,但我找不到真正有效的答案。有一个类似的,但速度根据行进的距离而变化。
So my problem is that I am trying to get an object (a player in this case) to move a long a straight line from point A to B at a constant speed. This is done by clicking on the player and dragging to where I want him to walk to, so it can be in any direction and over any distance.
所以我的问题是我试图让一个物体(在这种情况下是一个玩家)以恒定的速度从 A 点到 B 点移动一条长直线。这是通过点击玩家并拖动到我想让他走到的地方来完成的,所以它可以在任何方向和任何距离上。
I have some code that very nearly works, but the player always ends up slightly off course, more so the longer the distance he travels is. Here is that code:
我有一些几乎可以工作的代码,但玩家总是会稍微偏离路线,他行进的距离越长。这是代码:
window.addEventListener('mouseup', function(e) {
selectedPlayer.moveX = e.pageX;
selectedPlayer.moveY = e.pageY;
movePlayer(selectedPlayer);
});
function movePlayer(player) {
var xDistance = player.moveX - player.x;
var yDistance = player.moveY - player.y;
var travelDistance = Math.sqrt((xDistance * xDistance) + (yDistance * yDistance));
var timeToTravel = travelDistance; //This may seem pointless, but I will add a speed variable later
var playerAngle = Math.atan2(yDistance, xDistance) * (180 / Math.PI);
var xRatio = Math.atan2(xDistance, travelDistance);
var yRatio = Math.atan2(yDistance, travelDistance);
//This function is called in another part of code that repeats it 60 times a second
walkPlayer = function() {
setTimeout(function(){
player.x = player.moveX;
player.y = player.moveY;
selectedPlayer = undefined;
walkPlayer = undefined;
}, timeToTravel * 20)
player.angle = playerAngle;
player.x += xRatio;
player.y += yRatio;
};
}
I hope this makes sense, I've had to include only the part of the code that is relevant. I think my issue probably lies with the xRatio and yRatio parts, but I can't figure it out; I'm completely stumped.
我希望这是有道理的,我必须只包含相关的代码部分。我认为我的问题可能在于 xRatio 和 yRatio 部分,但我无法弄清楚;我完全被难住了。
EDIT: I'd like to add that playerAngle makes the player face in the direction of the drag, and that part works fine.
编辑:我想补充一点, playerAngle 使玩家面向拖动的方向,并且该部分工作正常。
回答by Loktar
Below are the basics required to get what you need working,
以下是获得所需工作所需的基础知识,
var tx = targetX - x,
ty = targetY - y,
dist = Math.sqrt(tx*tx+ty*ty),
rad = Math.atan2(ty,tx),
angle = rad/Math.PI * 180;;
velX = (tx/dist)*thrust;
velY = (ty/dist)*thrust;
player.x += velX
player.y += velY
This is a demo I did a while back which sounds like what you are looking for, I added the ability to click in order to change the target based off of your issue.
这是我不久前做的一个演示,听起来像您正在寻找的内容,我添加了单击功能,以便根据您的问题更改目标。
window.addEventListener('mouseup', function(e) {
targetX = e.pageX;
targetY = e.pageY;
});
var ctx = document.getElementById("canvas").getContext("2d"),
x = 300,
y = 0,
targetX = Math.random()*300,
targetY = Math.random()*300,
velX = 0,
velY = 0,
thrust = 5;
function draw(){
var tx = targetX - x,
ty = targetY - y,
dist = Math.sqrt(tx*tx+ty*ty),
rad = Math.atan2(ty,tx),
angle = rad/Math.PI * 180;;
velX = (tx/dist)*thrust;
velY = (ty/dist)*thrust;
// stop the box if its too close so it doesn't just rotate and bounce
if(dist > 1){
x += velX;
y += velY;
}
ctx.fillStyle = "#fff";
ctx.clearRect(0,0,400,400);
ctx.beginPath();
ctx.rect(x, y, 10, 10);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "#ff0";
ctx.beginPath();
ctx.rect(targetX, targetY, 10, 10);
ctx.closePath();
ctx.fill();
setTimeout(function(){draw()}, 30);
}
draw();
回答by Bergi
Your problem seems to be that xRatio
and yRatio
are angles, not vector coordinates. This should work:
您的问题似乎是,xRatio
并且yRatio
是角度,而不是矢量坐标。这应该有效:
document.addEventListener('mouseup', function(e) {
movePlayer(selectedPlayer, {x:e.pageX, y:e.pageY});
});
function movePlayer(player, target) {
var start = {
x: player.x,
y: player.y,
t: Date.now()
},
distance = Math.sqrt(distance.x*distance.x + distance.y*distance.y),
time = distance; //This may seem pointless, but I will add a speed variable later
difference = {
x: target.x - player.x,
y: target.y - player.y,
t: time
};
player.angle = Math.atan2(distance.y, distance.x) * (180 / Math.PI);
//This function is called in another part of code that repeats it 60 times a second
walkPlayer = function(curTime) { // we need timing information here: Date.now()
var elapsed = curTime - start.t,
ratio = elapsed / difference.t;
player.x = start.x + difference.x * ratio;
player.y = start.y + difference.y * ratio;
if (ratio >= 1) {
player.x = target.x;
player.y = target.y;
// end calling of walkPlayer
}
};
}