在c中使用三个垂直轴围绕自身旋转三角形

在c中使用三个垂直轴围绕自身旋转三角形,c,rotation,allegro,C,Rotation,Allegro,我需要绕自身旋转一个三角形(称为船)。 这是我到目前为止得到的,但它不起作用。它越来越小,直到消失 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(t

我需要绕自身旋转一个三角形(称为船)。
这是我到目前为止得到的,但它不起作用。它越来越小,直到消失

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是我要旋转的点,点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点。这样我的三角形就缩小了。
我使用cos(0.035)和sin(0.035),意思是2度。

我可以用int坐标复制快速收缩(同时旋转)。
(基于MCVE,这会容易得多……。
当坐标处于浮动状态时,收缩速度会慢得多,但仍会收缩

我认为这与您的实现以一种非常明显的方式收集所有数学错误(计算机总是这样)有关

为了避免完全缩水:
不要为了旋转而操纵相对坐标。相反,将相对坐标存储为常量,并将船舶方向存储为双精度角

然后通过增加/减少角度旋转(环绕,保持在-Pi…+Pi范围内)。
然后始终将变化的角度应用于恒定的相对坐标进行绘制

(如果您提供MCVE,我只能向您详细展示。)

这样,收集的错误只会导致轻微且缓慢增长的错误定位,
飞行员很可能不会注意到,然后由飞行员纠正。
“嗯,船还没有完成我想要的360度。哦,好吧,我再转一点。”

另一方面,我不相信使用角度作为cos()和sin()参数的方式。
或者换一种说法,我认为
theta=角度*(180/3.1415)->
θ=角度通过Pi进行U形转弯。
theta=角度*(180/3.1415)->
θ=角度*(3.1415/180)用于180度掉头。
对于您的实现,您得到了一个角度的U形转弯(Pi*3.1415/180),我看不出有什么原因


我还建议使用math.h中的适当常数(例如,
M_PI
),而不是您自己的小数点后4位的常数。

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);
}
如维基百科文章中所定义。请注意,原始坐标、
x_original
y_original
(或船舶结构中
形状[]
数组中的值)从未修改


通过这种方式,你可以让玩家“升级”他们的飞船,只需将
形状更改为指向一个新的飞船形状,并将
顶点更改为反映该数字。

为什么不起作用?你做了什么来调试它?它消失了。绘图功能是这样的:
void drawShip(Ship*Ship){al_draw_三角形(Ship->center.x+Ship->A.x,Ship->center.y+Ship->A.y,Ship->center.x+Ship->B.y,Ship->center.x+Ship->C.x,Ship->center.y+Ship->C.y,Ship->color,1)}
当我按键旋转它时,它消失了。我的数学一定有问题,但我想不出是什么问题。请做一个,不需要整个绘图和其他图形,只需要一个main()来打印几次坐标;演示它们是如何变小的,尤其是速度有多快。除此之外,我想看看你们使用的坐标类型。智力?浮动双精度?相对于中心坐标变小了吗?还是船也朝(0,0)方向移动?你想要

    x_current = x_center + x_original * cos(direction) - y_original * sin(direction);
    y_current = y_center + x_original * sin(direction) + y_original * cos(direction);