我需要围绕自身旋转一个三角形(称为船)。
这是我到目前为止得到的,但它不起作用。它越来越小,直到消失。
void RotatePoint(Point *P, float angle)
{
float theta = angle * (180/3.1415);
P->x = (P->x * cos(theta)) - (P->y * sin(theta));
P->y = (P->y * cos(theta)) + (P->x * sin(theta));
}
void RotateShip(Ship *ship)
{
Rotate(&ship->A, rotateAngle);
Rotate(&ship->B, rotateAngle);
Rotate(&ship->C, rotateAngle);
}
P点是我要旋转的Point,C点是三角形的中心。我想如果我旋转所有三个顶点,三角形就会旋转。
在我的例子中,我这样初始化:
void initShip(Ship *ship)
{
ship->center.x = (SCREEN_W)/2.0;
ship->center.y = (SCREEN_H)/2.0;
ship->A.x = 0;
ship->A.y = -5;
ship->B.x = 15;
ship->B.y = 25;
ship->C.x = -15;
ship->C.y = 25;
ship->color = al_map_rgb(255, 255, 255);
}
船A、B、C是到三角形中心的距离。我将 A、B 和 C 添加到中心顶点来绘制它。
A=-0.699857,-19.963261
A=-0.000857,-19.951065
A=-0.699001,-19.914387
A=-0.001712,-19.902250
A=-0.698147,-19.865631
A=-0.002565,-19.853554
我向后按一个键,向后按一个键,使其顺时针和逆时针旋转。注意 A 是如何收缩的。 我不知道我在做什么。当它到达顶部时,我应该回到 20.00。这样我的三角形就缩小了。 我使用的是 cos(0.035) 和 sin(0.035),意思是 2 度。
最佳答案
OP 有一个典型的错误:在应该使用原始/初始值的地方使用临时(或中间)值。
作为一个简化的示例,考虑这样一种情况,您有三个变量,a
、b
和 c
,并且想要旋转它们向左赋值一个变量:
a = b;
b = c;
c = a; /* Oops! Won't work! */
最后的赋值是个问题,因为a
已经不是原来的值了!您不能以可以避免此问题的方式对作业进行排序;唯一改变的是哪个变量会遇到这个问题。要解决这个问题,您需要使用一个新的临时变量来保存原始值:
t = a;
a = b;
b = c;
c = t;
在 OP 的情况下,船舶结构不应在相同的变量中混合船舶的当前形状和船舶的真实/未旋转形状。即使您避免了上述问题,您仍然会遭受累积的舍入误差;这可能需要几个小时的游戏时间,但最终你的船会看起来不一样。
解决方案是在单独的变量中描述船舶形状,或者在船舶更新函数中使用常量。)
假设我们有一个变量 dir
以弧度指定方向,从上逆时针旋转,0 向上(朝向负 y 轴),π/2(和 -3π/2)向左(朝向负 x 轴)、π(和 -π)向下、3π/2(和 -π/2)向右,等等。如果 deg
以度为单位,则 dir = deg * 3.14159265358979323846/180.0
。我们也可以使用atan2()
函数来找出dir
:dir = atan2(-x, y)
。
当 dir = 0
时,OP 需要 A = { 0, -5 }
,B = { 15, 25 }
,并且 C = { -15, 25 }
。如果我们定义 Adir = 3.14159
, Ar = 5
, Bdir = -0.54042
, Br = sqrt(15*15+25* 25) = 29.15476
,Cdir = 0.54042
,Cr = 29.15476
,那么船的顶点是
A.x = center.x + Ar*sin(dir + Adir);
A.y = center.y + Ar*cos(dir + Adir);
B.x = center.x + Br*sin(dir + Bdir);
B.y = center.y + Br*cos(dir + Bdir);
C.x = center.x + Cr*sin(dir + Cdir);
C.y = center.y + Cr*cos(dir + Cdir);
如果 OP 想在 rotateShip 函数中修复船的形状,那么
void rotateShip(Ship *s, double rotateAngle)
{
s->A.x = s->center.x + 5.00000 * sin(rotateAngle + 3.14159);
s->A.y = s->center.y + 5.00000 * cos(rotateAngle + 3.14159);
s->B.x = s->center.x + 29.15476 * sin(rotateAngle - 0.54042);
s->B.y = s->center.y + 29.15476 * cos(rotateAngle - 0.54042);
s->C.x = s->center.x + 29.15476 * sin(rotateAngle + 0.54042);
s->C.y = s->center.y + 29.15476 * cos(rotateAngle + 0.54042);
}
就个人而言,我会使用可变数量的顶点来定义船的形状:
typedef struct {
double x;
double y;
} vec2d;
typedef struct {
vec2d center;
size_t vertices;
const vec2d *shape; /* Un-rotated ship vertices */
double direction; /* Ship direction, in radians */
vec2d *vertex; /* Rotated ship vertices */
} Ship;
const vec2d default_shape[] = {
{ 0.0, -5.0 },
{ -15.0, 25.0 },
{ 15.0, 25.0 },
};
void updateShip(Ship *ship)
{
const double c = cos(ship->direction);
const double s = sin(ship->direction);
size_t i;
for (i = 0; i < ship->vertices; i++) {
ship->vertex[i].x = ship->center.x + c*ship->shape[i].x - s*ship->shape[i].y;
ship->vertex[i].y = ship->center.y + s*ship->shape[i].x + c*ship->shape[i].y;
}
}
void initShip(Ship *ship, const size_t vertices, const vec2d *shape)
{
ship->center.x = 0.5 * SCREEN_W;
ship->center.y = 0.5 * SCREEN_H;
if (vertices > 2 && shape != NULL) {
ship->vertices = vertices;
ship->shape = shape;
} else {
ship->vertices = (sizeof default_shape) / (sizeof default_shape[0]);
ship->shape = default_shape;
}
ship->direction = 0;
ship->vertex = malloc(ship->vertices * sizeof ship->vertex[0]);
if (!ship->vertex) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
updateShip(ship);
}
在 updateShip
中,我们使用 ship->direction
的 2D 旋转,旋转由 shape[]
中的顶点指定的船舶模型,将旋转和平移的坐标保存到 vertex[]
。
x_current = x_center + x_original * cos(direction) - y_original * sin(direction);
y_current = y_center + x_original * sin(direction) + y_original * cos(direction);
如定义关于 rotation 的维基百科文章.请注意,原始坐标 x_original
和 y_original
(或 Ship 结构中 shape[]
数组中的值)永远不会被修改。
通过这种方式,您可以让玩家“升级”他们的飞船,只需更改 shape
以指向新的飞船形状,并更改 vertices
以反射(reflect)该数字。
关于c - 使用三个顶点在 c 中围绕自身旋转一个三角形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44742097/