gpt4 book ai didi

javascript - Javascript canvas lineTo,要在一定距离后停止

转载 作者:行者123 更新时间:2023-12-03 05:13:09 25 4
gpt4 key购买 nike

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

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



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

var turret = {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 = "red";
c.fillRect(turret.x, turret.y, turret.w, turret.h);

c.fillStyle = "yellow";
c.fillRect(randomBox.x, randomBox.y, randomBox.w, randomBox.h);


c.beginPath();
c.moveTo(turret.x + (turret.w/2), turret.y + (turret.h/2));
c.lineTo(randomBox.x, randomBox.y);
c.stroke();

#canvas {
background-color: #eee;

}

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<canvas id="canvas" width=500 height=500></canvas>
</body>
</html>

最佳答案

向量数学。

可以将一条线视为一个坐标和一个向量,该向量描述了从起始坐标到终点的方向和距离。当您通过一条线的端点描述一条线时,您将使用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部分除以其总长度即可(如上所述)

// normalise vector
var nx = vx / mag; // n for normal
var ny = vy / mag;


缩放正常

现在您有了代表线方向的单位矢量,现在很容易找到距起点固定距离的点。就像在数字行上一样,如果您希望点从5变为10,则将10加到5。但是,它也与10“单位”到5或 10 * 1 + 5相同。在几何中,单位是单位向量。

因此,如果我们希望点从起点开始为10个单位(像素),则将单位矢量的两个分量都乘以10,并将它们添加到起点坐标中。

var endX = x1 + nx * 10;
var endY = y1 + ny * 10;


现在endX,endY距行起点10像素。



向量数学。

如您所见,有了单位矢量,可以轻松地从起点到任意距离的任何点。

所有矢量库均包含上述矢量和坐标操作。我们将两个坐标(x,y)的集合称为2D向量 vec,并且我们有 add()sub()multiply()divide()magnitude()normalise()等操作同样方便的操作,例如 cross()dot(),但这暂时不在此问题的范围内。

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



对你的问题

我已经复制了您的代码并进行了一些更改。我在上述数学上也做了一些捷径。与将任何一组公式组合在一起一样,您可以简化它们以获得更有效和易于理解的公式。这在游戏中特别容易做,在这种游戏中,您可能每秒进行数百万次至数百万次的计算。

函数 drawLineLength使用线段x1,y1,x2,y2和maxLen值绘制一条长度不超过 maxLen个像素的线。

如果您有任何疑问,请在评论中提出。

您的代码针对您的问题进行了调整。



var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
c.lineWidth = 4;
c.lineCap = "round";
var turret = {x:20, y:20, w:20, h:20};
const maxLineLength = 50; // max length of line in pixels
var rBox = { // FKA randomBox
x : 0,
y : 0,
w : 40,
h : 40
};

// drawLineLength draws a line with maximum length
// x1,y1 from
// x2,y2 line to
// maxLen the maximum length of the line. If line is shorter it will not be changed
function drawLineLength (x1, y1, x2, y2, maxLen) {
var vx = x2 - x1; // get dist between start and end of line
var vy = y2 - y1; // for x and y

// use pythagoras to get line total length
var mag = Math.sqrt(vx * vx + vy * vy);
if (mag > maxLen) { // is the line longer than needed?

// calculate how much to scale the line to get the correct distance
mag = maxLen / mag;
vx *= mag;
vy *= mag;
}
c.beginPath();
c.moveTo(x1, y1);
c.lineTo(x1 + vx, y1 + vy);
c.stroke();
}
// Test function is on a timer and run every 500ms (1/2 second)
function doTest () {
// clear the canvas of last render
c.clearRect(0, 0, canvas.width, canvas.height);

// find a random position for the box inside the canvas and 10 pixels from any edge
rBox.x = 10 + Math.random() * (canvas.width - rBox.w - 20);
rBox.y = 10 + Math.random() * (canvas.height - rBox.h - 20);

// draw both objects
c.fillStyle = "red";
c.fillRect(turret.x, turret.y, turret.w, turret.h);

c.fillStyle = "yellow";
c.fillRect(rBox.x, rBox.y, rBox.w, rBox.h);

// call function to draw line that will have a maximum length
drawLineLength(
turret.x + turret.w / 2,
turret.y + turret.h / 2,
rBox.x + rBox.w / 2,
rBox.y + rBox.h / 2,
maxLineLength
);
setTimeout(doTest,500);
}
doTest();

#canvas { background-color: #eee;  }

<canvas id="canvas" width=500 height=500></canvas>

关于javascript - Javascript canvas lineTo,要在一定距离后停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41720852/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com