Javascript画布lineTo,希望在一定距离后停止

Javascript画布lineTo,希望在一定距离后停止,javascript,canvas,Javascript,Canvas,我正在做一个单独的项目,我试图画一条从炮塔到敌人的线。但我希望这条线保持在炮塔的边界内,而不是一直延伸到敌人。我制作的一个较小的示例可以在下面的代码片段中找到 请仔细回答,因为我绝对不是专家。非常感谢!谢谢 var canvas=document.getElementById(“canvas”); var c=canvas.getContext(“2d”); var炮塔={x:20,y:20,w:20,h:20}; var randomBox={x:30+Math.random()*300,y

我正在做一个单独的项目,我试图画一条从炮塔到敌人的线。但我希望这条线保持在炮塔的边界内,而不是一直延伸到敌人。我制作的一个较小的示例可以在下面的代码片段中找到

请仔细回答,因为我绝对不是专家。非常感谢!谢谢

var canvas=document.getElementById(“canvas”);
var c=canvas.getContext(“2d”);
var炮塔={x:20,y:20,w:20,h:20};
var randomBox={x:30+Math.random()*300,y:30+Math.random()*300,w:40,h:40};
c、 fillStyle=“红色”;
c、 fillRect(转塔x、转塔y、转塔w、转塔h);
c、 fillStyle=“黄色”;
c、 fillRect(randomBox.x,randomBox.y,randomBox.w,randomBox.h);
c、 beginPath();
c、 移动到(转塔x+(转塔w/2)、转塔y+(转塔h/2));
c、 lineTo(randomBox.x,randomBox.y);
c、 笔划()
#画布{
背景色:#eee;
}

JS-Bin
矢量数学。 直线可以看作是坐标和向量,向量描述了从起点坐标到终点的方向和距离。通过端点描述直线时,使用的是2个坐标。通常我们把一条有起点和终点的线称为线段,而不是实际上无限长的线

直线段作为坐标

 var x1 = 100;
 var y1 = 100;
 var x2 = 300;
 var y2 = 400;
线段向量 要获得直线的矢量分量,只需从终点减去起点。向量是一种直线段,其起点始终位于坐标0,0处

 var vx = x2 - x1;  // v for vector
 var vy = y2 - y1;
大小或长度 所有向量的大小(或长度)都是正的,这取决于长度的计算方式。向量的x和y分量构成三角形的两条较短边,沿着向量的直线是最长的直线,即斜边

我们使用毕达哥拉斯来计算向量的大小

var mag = Math.sqrt(vx * vx + vy * vy); // mag for magnitude
归一化向量 在许多关于线的情况下(如本例中),我们对线的长度不太感兴趣,而只对方向感兴趣。为了便于计算,我们喜欢使用一种特殊形式的向量,称为单位向量。这是一个长度正好为1个单位的向量(在我们的示例1中,单位为像素)

单位向量具有许多在进行几何运算时非常有用的特性

创建单位向量的过程称为归一化。只需将向量的x,y部分除以其总长度即可(如上计算)

缩放法线 现在有了表示直线方向的单位向量,很容易找到距起点固定距离的点。就像在数字线上,如果你想要一个点,比如说,从5加10到5。但它也与10“单位”到5或
10*1+5
相同。在几何学中,单位是单位向量

因此,如果我们希望点从起点算起10个单位(像素),我们将单位向量的两个分量乘以10,然后将它们添加到起点坐标

var endX = x1 + nx * 10;
var endY = y1 + ny * 10;
现在endX,endY距离直线起点10像素


向量数学。 正如您所看到的,使用单位向量可以很容易地从起点获得任意距离的任意点

所有矢量库都包含上述矢量和坐标操作。我们把一组两个坐标(x,y)称为二维向量
vec
,我们有一些操作,比如
add()
sub()
multiply()
divide()
magnity()
normalize()
,还有一些同样方便的操作,比如
cross()
dot()
但这已经超出了这个问题的范围

如果您对编写游戏感兴趣,我强烈建议您编写自己的小型2D向量库,创建该库不超过一个小时(如果您是编程新手,可能需要两个小时),并且您将学习编写几乎任何类型游戏所需的一些基本数学技能(顺便说一句,3D矢量数学与2D几乎相同,只是有一个称为z的额外组件)


解决你的问题 我复制了你的代码并做了一些修改。我也在上面描述的数学中采取了一些捷径。就像任何一组公式一样,如果你把它们放在一起,你可以简化它们,得到一个更有效、更容易理解的公式。这是在游戏中特别需要做的一件事,在游戏中,你可能要做一些计算每秒有100到100百万次

函数
drawLineLength
采用线段x1、y1、x2、y2和值maxLen绘制长度不超过
maxLen
像素的直线

如果你有问题,请在评论中提问

您的代码根据您的问题进行了调整。
var canvas=document.getElementById(“canvas”);
var c=canvas.getContext(“2d”);
c、 线宽=4;
c、 lineCap=“圆形”;
var炮塔={x:20,y:20,w:20,h:20};
const maxLineLength=50;//以像素为单位的最大行长度
var rBox={//FKA随机框
x:0,,
y:0,
w:40,
h:40
};
//drawLineLength以最大长度绘制线
//x1,y1来自
//x2、y2线至
//maxLen行的最大长度。如果行较短,则不会更改
函数drawLineLength(x1、y1、x2、y2、maxLen){
var vx=x2-x1;//获取行的开始和结束之间的距离
var vy=y2-y1;//对于x和y
//使用毕达哥拉斯获得线条的总长度
var mag=数学sqrt(vx*vx+vy*vy);
如果(mag>maxLen){//行是否比需要的长?
//计算要缩放多少线才能获得正确的距离
mag=最大值/最大值;
vx*=mag;
vy*=mag;
}
c、 beginPath();
c、 moveTo(x1,y1);
c、 lineTo(x1+vx,y1+vy);
c、 笔划();
}
//测试功能在计时器上,每500毫秒(1/2秒)运行一次
函数doTest(){
//清除上次渲染的画布
c、 clearRect(0,0,can
var endX = x1 + nx * 10;
var endY = y1 + ny * 10;