游戏开发中的三角数学

发布于 2024-07-08 15:34:00 字数 338 浏览 10 评论 0原文

我试图制作一个三角形(等腰三角形)来在屏幕上移动,同时当用户按下方向键(如向右或向左)时稍微旋转它。

我希望三角形的鼻子(顶点)始终引导三角形。 (就像那个古老的小行星游戏)。

我的问题在于这背后的数学。 在每个 X 时间间隔,我希望三角形朝“某个方向”移动,我需要帮助找到这个方向(x 和 y 递增/递减)。

我可以找到三角形的中心点(质心),并且我有最上面的 x 和 y 点,所以我有一个线向量可以使用,但不知道“如何”使用它。

我认为这与旧的 Sin 和 Cos 方法以及三角形旋转的量(角度)有关,但我对这些东西有点生疏。

任何帮助是极大的赞赏。

I'm trying to make a triangle (isosceles triangle) to move around the screen and at the same time slightly rotate it when a user presses a directional key (like right or left).

I would like the nose (top point) of the triangle to lead the triangle at all times. (Like that old asteroids game).

My problem is with the maths behind this. At every X time interval, I want the triangle to move in "some direction", I need help finding this direction (x and y increments/decrements).

I can find the center point (Centroid) of the triangle, and I have the top most x an y points, so I have a line vector to work with, but not a clue as to "how" to work with it.

I think it has something to do with the old Sin and Cos methods and the amount (angle) that the triangle has been rotated, but I'm a bit rusty on that stuff.

Any help is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

原来是傀儡 2024-07-15 15:34:00

vy/vx 的反正切(反正切)(其中 vx 和 vy 是(质心 -> 尖端)向量的分量)给出向量所面对的角度。

经典反正切给你一个归一化为 -90° < 的角度。 r < 但是,+90° 度,因此您必须根据结果的符号和 vx 的符号从结果中添加或减去 90 度。

幸运的是,您的标准库应该提供一个 atan2() 函数,该函数将 vx 和 vy 分别作为参数,并返回 0° 到 360° 或 -180° 到 +180° 之间的角度。 它还会处理 vx=0 的特殊情况,如果不小心,就会导致除以零。

请参阅 http://www.arctangent.net/atan.html 或仅搜索“arctangent” ”。

编辑:为了清楚起见,我在帖子中使用了度数,但 Java 和许多其他语言/库以弧度工作,其中 180° = π。

您还可以将 vx 和 vy 添加到三角形的点,使其沿“向前”方向移动,但请确保矢量已标准化 (vx² + vy² = 1),否则速度将取决于三角形的大小。

The arctangent (inverse tangent) of vy/vx, where vx and vy are the components of your (centroid->tip) vector, gives you the angle the vector is facing.

The classical arctangent gives you an angle normalized to -90° < r < +90° degrees, however, so you have to add or subtract 90 degrees from the result depending on the sign of the result and the sign of vx.

Luckily, your standard library should proive an atan2() function that takes vx and vy seperately as parameters, and returns you an angle between 0° and 360°, or -180° and +180° degrees. It will also deal with the special case where vx=0, which would result in a division by zero if you were not careful.

See http://www.arctangent.net/atan.html or just search for "arctangent".

Edit: I've used degrees in my post for clarity, but Java and many other languages/libraries work in radians where 180° = π.

You can also just add vx and vy to the triangle's points to make it move in the "forward" direction, but make sure that the vector is normalized (vx² + vy² = 1), else the speed will depend on your triangle's size.

和影子一齐双人舞 2024-07-15 15:34:00

@Mark:

我已经尝试在这个答案框中写两次有关向量、坐标、点和角度的入门知识,但两次都改变了主意,因为这会花费太长时间,而且我确信有很多教程可以解释这些内容比我以前能做的更好。

您的质心和“尖端”坐标不是向量;而是向量。 也就是说,将它们视为向量没有任何好处。

您想要的向量 vForward = pTip - pCentroid 可以通过质心点减去“尖端”角的坐标来计算。 该向量的 atan2(),即 atan2(tipY-centY,tipX-centX),为您提供三角形“面向”的角度。

至于它与什么相关,并不重要。 您的库可能会使用这样的约定:递增的 X 轴(---> 大概您见过的所有 2D 图形上的右/东方向)为 0° 或 0π。 增加的 Y(顶部、北)方向将对应于 90° 或 (1/2)π。

@Mark:

I've tried writing a primer on vectors, coordinates, points and angles in this answer box twice, but changed my mind on both occasions because it would take too long and I'm sure there are many tutorials out there explaining stuff better than I ever can.

Your centroid and "tip" coordinates are not vectors; that is to say, there is nothing to be gained from thinking of them as vectors.

The vector you want, vForward = pTip - pCentroid, can be calculated by subtracting the coordinates of the "tip" corner from the centroid point. The atan2() of this vector, i.e. atan2(tipY-centY, tipX-centX), gives you the angle your triangle is "facing".

As for what it's relative to, it doesn't matter. Your library will probably use the convention that the increasing X axis (---> the right/east direction on presumably all the 2D graphs you've seen) is 0° or 0π. The increasing Y (top, north) direction will correspond to 90° or (1/2)π.

小猫一只 2024-07-15 15:34:00

在我看来,您需要存储三角形的旋转角度以及可能的当前速度。

x' = x + speed * cos(angle)
y' = y + speed * sin(angle)

请注意,角度的单位是弧度,而不是度数!

Radians = Degrees * RadiansInACircle / DegreesInACircle

RadiansInACircle = 2 * Pi

DegressInACircle = 360

对于顶点的位置,每个顶点都位于距中心一定的距离和角度处。 在进行此计算之前添加当前旋转角度。 这与计算运动的数学原理相同。

It seems to me that you need to store the rotation angle of the triangle and possibly it's current speed.

x' = x + speed * cos(angle)
y' = y + speed * sin(angle)

Note that angle is in radians, not degrees!

Radians = Degrees * RadiansInACircle / DegreesInACircle

RadiansInACircle = 2 * Pi

DegressInACircle = 360

For the locations of the vertices, each is located at a certain distance and angle from the center. Add the current rotation angle before doing this calculation. It's the same math as for figuring the movement.

丑丑阿 2024-07-15 15:34:00

还有更多内容:

向量表示位移。 位移、平移、运动或者任何你想称呼的东西,如果没有起点,都是没有意义的,这就是为什么我将上面的“向前”向量称为“从质心”,这就是为什么“质心向量”,即带有质心点的 x/y 分量没有意义。 这些分量为您提供质心点相对于原点的位移。 换句话说,pOrigin + vCentroid = pCentroid。 如果从 0 点开始,然后添加代表质心点位移的向量,就得到质心点。

注意:

向量+向量=向量
(两个位移相加得到第三个不同的位移)

点+向量=点
(移动/替换一个点会得到另一个点)

点 + 点 = ???
(添加两个点没有意义;但是:)

点 - 点 = 矢量
(两点之差是它们之间的位移)

现在,这些位移可以(至少)两种不同的方式来考虑。 您已经熟悉的是矩形 (x, y) 系统,其中矢量的两个分量分别表示 x 和 y 方向上的位移。 但是,您也可以使用坐标(r,θ)。 这里,θ 代表位移的方向(以相对于任意零角度的角度),r 代表距离。

以 (1, 1) 向量为例。 它表示在我们都习惯看到的坐标系中向右移动一个单位和向上移动一个单位。 该矢量的极坐标为 (1.414, 45°); 相同的运动,但表示为“在 45° 角方向上的 1.414 个单位的位移。(再次使用方便的极坐标系,其中东方向为 0°,角度逆时针增加。)

极坐标和直角坐标为:

θ = atan2(y, x)
r = sqrt(x²+y²)(现在您看到直角三角形在哪里了吗?)

,反之,

x = r * cos(θ)
y = r * sin(θ)

现在,由于从三角形质心到“尖端”角绘制的线段将代表三角形“面向”的方向,如果我们要获得向量平行于该线(例如vForward = pTip - pCentroid),该向量的 θ 坐标将对应于三角形所面对的角度。

再次取 (1, 1) 向量。 如果这是 vForward,则意味着您的“尖端”点的 x 和 y 坐标都比质心的 x 和 y 坐标多 1。 假设质心位于 (10, 10)。 这会将“尖端”角置于 (11, 11) 处。 (记住,pTip = pCentroid + vForward,通过在上一个方程的两边添加“+ pCentroid”来实现。)现在这个三角形面向哪个方向? 45°,对吗? 这就是 (1, 1) 向量的 θ 坐标!

Here's some more:

Vectors represent displacement. Displacement, translation, movement or whatever you want to call it, is meaningless without a starting point, that's why I referred to the "forward" vector above as "from the centroid," and that's why the "centroid vector," the vector with the x/y components of the centroid point doesn't make sense. Those components give you the displacement of the centroid point from the origin. In other words, pOrigin + vCentroid = pCentroid. If you start from the 0 point, then add a vector representing the centroid point's displacement, you get the centroid point.

Note that:

vector + vector = vector
(addition of two displacements gives you a third, different displacement)

point + vector = point
(moving/displacing a point gives you another point)

point + point = ???
(adding two points doesn't make sense; however:)

point - point = vector
(the difference of two points is the displacement between them)

Now, these displacements can be thought of in (at least) two different ways. The one you're already familiar with is the rectangular (x, y) system, where the two components of a vector represent the displacement in the x and y directions, respectively. However, you can also use polar coordinates, (r, Θ). Here, Θ represents the direction of the displacement (in angles relative to an arbitary zero angle) and r, the distance.

Take the (1, 1) vector, for example. It represents a movement one unit to the right and one unit upwards in the coordinate system we're all used to seeing. The polar equivalent of this vector would be (1.414, 45°); the same movement, but represented as a "displacement of 1.414 units in the 45°-angle direction. (Again, using a convenient polar coordinate system where the East direction is 0° and angles increase counter-clockwise.)

The relationship between polar and rectangular coordinates are:

Θ = atan2(y, x)
r = sqrt(x²+y²) (now do you see where the right triangle comes in?)

and conversely,

x = r * cos(Θ)
y = r * sin(Θ)

Now, since a line segment drawn from your triangle's centroid to the "tip" corner would represent the direction your triangle is "facing," if we were to obtain a vector parallel to that line (e.g. vForward = pTip - pCentroid), that vector's Θ-coordinate would correspond to the angle that your triangle is facing.

Take the (1, 1) vector again. If this was vForward, then that would have meant that your "tip" point's x and y coordinates were both 1 more than those of your centroid. Let's say the centroid is on (10, 10). That puts the "tip" corner over at (11, 11). (Remember, pTip = pCentroid + vForward by adding "+ pCentroid" to both sides of the previous equation.) Now in which direction is this triangle facing? 45°, right? That's the Θ-coordinate of our (1, 1) vector!

当梦初醒 2024-07-15 15:34:00

保持质心在原点。 使用从质心到鼻子的向量作为方向向量。 http://en.wikipedia.org/wiki/Cooperative_rotation#Two_dimensions 将旋转此向量。 从这个向量构造另外两个点。 将三个点移动到屏幕上的位置并进行绘制。

keep the centroid at the origin. use the vector from the centroid to the nose as the direction vector. http://en.wikipedia.org/wiki/Coordinate_rotation#Two_dimensions will rotate this vector. construct the other two points from this vector. translate the three points to where they are on the screen and draw.

美羊羊 2024-07-15 15:34:00
double v; // velocity
double theta; // direction of travel (angle)
double dt; // time elapsed

// To compute increments
double dx = v*dt*cos(theta);
double dy = v*dt*sin(theta);

// To compute position of the top of the triangle
double size; // distance between centroid and top
double top_x = x + size*cos(theta);
double top_y = y + size*sin(theta);
double v; // velocity
double theta; // direction of travel (angle)
double dt; // time elapsed

// To compute increments
double dx = v*dt*cos(theta);
double dy = v*dt*sin(theta);

// To compute position of the top of the triangle
double size; // distance between centroid and top
double top_x = x + size*cos(theta);
double top_y = y + size*sin(theta);
泪意 2024-07-15 15:34:00

我可以看到我需要将常见的二维旋转公式应用于我的三角形才能得到结果,我只是在处理不同组件之间的关系时遇到了一些麻烦。

aib 表示:

反正切(反正切)
vy/vx,其中 vx 和 vy 是
你的(质心->尖端)的组成部分
向量,给出向量的角度
正面临着。

vx 和 vy 是质心或尖端的 x 和 y 坐标吗? 我认为我对这里的“向量”术语感到困惑。 我的印象是向量只是二维(在本例中)空间中代表方向的点。

那么这种情况下,centroid->tip的向量是如何计算的呢? 仅仅是质心吗?

meyahoocomlorenpechtel 指出:

在我看来,你需要存储
三角形的旋转角度和
可能是当前速度。

相对于什么旋转角度? 三角形的原点,还是游戏窗口本身? 另外,对于未来的旋转,角度是上次旋转的角度还是三角形的原始位置?

感谢大家迄今为止的帮助,我真的很感激!

I can see that I need to apply the common 2d rotation formulas to my triangle to get my result, Im just having a little bit of trouble with the relationships between the different components here.

aib, stated that:

The arctangent (inverse tangent) of
vy/vx, where vx and vy are the
components of your (centroid->tip)
vector, gives you the angle the vector
is facing.

Is vx and vy the x and y coords of the centriod or the tip? I think Im getting confused as to the terminology of a "vector" here. I was under the impression that a Vector was just a point in 2d (in this case) space that represented direction.

So in this case, how is the vector of the centroid->tip calculated? Is it just the centriod?

meyahoocomlorenpechtel stated:

It seems to me that you need to store
the rotation angle of the triangle and
possibly it's current speed.

What is the rotation angle relative to? The origin of the triangle, or the game window itself? Also, for future rotations, is the angle the angle from the last rotation or the original position of the triangle?

Thanks all for the help so far, I really appreciate it!

别把无礼当个性 2024-07-15 15:34:00

您将希望最上面的顶点作为质心,以达到所需的效果。

you will want the topmost vertex to be the centroid in order to achieve the desired effect.

墨落画卷 2024-07-15 15:34:00

首先,我将从质心开始,而不是计算它。 你知道三角形的质心位置和旋转角度,我将用它来计算顶点的位置。 (对于任何语法错误,我提前表示歉意,我刚刚开始涉足 Java。)

//起点

double tip_x = 10;
double tip_y = 10;

should be

double center_x = 10;
double center_y = 10;

//三角形详细信息

int width = 6; //base
int height = 9;

应该是 3 个角度、距离对的数组。

angle = rotation_angle + vertex[1].angle;
dist = vertex[1].distance;    
p1_x = center_x + math.cos(angle) * dist;
p1_y = center_y - math.sin(angle) * dist;
// and the same for the other two points

请注意,我减去 Y 距离。 屏幕空间是颠倒的,这一事实让您感到困惑。 在我们看来,Y 随着你的上升而增加——但屏幕坐标并不是这样工作的。

如果您跟踪位置和旋转角度而不是导出旋转角度,那么数学会简单得多。

另外,在最后一段代码中,您将通过旋转角度修改位置。 结果将是你的船在每个更新周期都会转动一定的旋转角度。 我认为目标是小行星之类的东西,而不是一只追尾巴的猫!

First, I would start with the centroid rather than calculate it. You know the position of the centroid and the angle of rotation of the triangle, I would use this to calculate the locations of the verticies. (I apologize in advance for any syntax errors, I have just started to dabble in Java.)

//starting point

double tip_x = 10;
double tip_y = 10;

should be

double center_x = 10;
double center_y = 10;

//triangle details

int width = 6; //base
int height = 9;

should be an array of 3 angle, distance pairs.

angle = rotation_angle + vertex[1].angle;
dist = vertex[1].distance;    
p1_x = center_x + math.cos(angle) * dist;
p1_y = center_y - math.sin(angle) * dist;
// and the same for the other two points

Note that I am subtracting the Y distance. You're being tripped up by the fact that screen space is inverted. In our minds Y increases as you go up--but screen coordinates don't work that way.

The math is a lot simpler if you track things as position and rotation angle rather than deriving the rotation angle.

Also, in your final piece of code you're modifying the location by the rotation angle. The result will be that your ship turns by the rotation angle every update cycle. I think the objective is something like Asteroids, not a cat chasing it's tail!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文