2017-06-25 14 views
1

三角形(船と呼ばれる)を回転させる必要があります。
これまで私がこれまでに得たことはありますが、動作しません。それが消えるまでそれは小さくなり続けます。3つの頂点を使用してcで三角形を回転する

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は三角形の中心点です。 3つの頂点をすべて回転させると、三角形が回転すると私は考えました。私の場合

、私はこの方法を初期化:

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 

私は、1つのキーを1つ前に押して、時計回りと反時計回りに回転させます。どのようにAが縮小しているかに注目してください。 私は何をしているのか分かりません。私は20.00に戻って、トップに達するはずです。この方法で私の三角形は縮小しています。 私は2度を意味するcos(0.035)とsin(0.035)を使用しています。

+0

なぜ機能しないのですか?あなたはそれをデバッグするために何をしましたか? – nicomp

+0

それはただ消える。描画機能は 'void drawShip(Ship * ship){ \t al_draw_triangle(ship-> center.x + ship-> Ax、船 - >センター.y +船 - > Ay、船 - >センター) x +船 - > Bx、船 - >センター.y +船 - >バイ、船 - >センターx +船 - > Cx、船 - >センターy-船 - > Cy、 ; } ' キーを押して回転させると消えます。私の数学で何かが間違っているはずですが、私は何が分かりません。 –

+0

[mcve]を作ってください。図面やその他のグラフィックスは必要ありません。また、main()は座標値を出力します。どのように小さくなっているかを実証しています。 – Yunnosch

答えて

0

intの座標を使用して高速縮みを(回転させながら)再現することができます。
(それはMCVEに基づいて非常に簡単だったでしょう....)。
座標がfloatの場合、ずっとゆっくりと縮小しますが、それでも縮小します。

私は実装がすべての数学エラー(コンピュータが常に作成する)を非常に目に見える形で収集するという事実に関連しています。

完全に縮小しないようにするために:
を回転させるために、相対座標を操作しないでください。代わりに相対座標を定数として格納し、船の向きを二重の角度で格納します。

次に、角度を増減して回転させます(折り返し、-Pi ... + Piの範囲内に留まるようにします)。
次に、一定の相対座標に常に変化する角度を適用して描画します。最も可能性が高い気づいたことはありません

(あなたがMCVEを提供する場合、私はのみ、詳細にお見せすることができます。)

この方法では、収集したエラーはわずかで、ゆっくりと成長方位誤差になり、
パイロットによって訂正されます。
"うーん、船はまだ私が望んでいた360を完了していない。ああ、もう少し進むだろう。

私はcos()とsin()のパラメータとして角度を使用する方法を信頼しません。
違う言い方をすると、私は、UターンPiの場合、
theta = angle * (180/3.1415); - >theta = angle;と思います。
theta = angle * (180/3.1415); - >theta = angle * (3.1415/180); Uターンビア180.
あなたの実装には、角度(Pi * 3.1415/180)のUターンがありますが、その理由はわかりません。

math.hの適切な定数を使用することをおすすめします(例:M_PI)の代わりに、小数点以下4桁の定数を使用します。

1

OPには古典的なバグがあります。元の/初期値を代わりに使用する必要がある一時的な(または中間の)値を使用しています。簡単な例として、

は、次の3つの変数、 ab、および 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です。 dirdir = atan2(-x, y)を見つけるには、atan2()関数を使用することもできます。

dir = 0の場合、OPはA = { 0, -5 },B = { 15, 25 }およびC = { -15, 25 }を望んでいます。我々はAdir = 3.14159Ar = 5Bdir = -0.54042Br = sqrt(15*15+25*25) = 29.15476、、およびCr = 29.15476を定義した場合OPは、その後

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); 
} 

、rotateShip機能で船の形状を固定したい場合には、船の頂点が

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); 

です

私は個人的に、可変数の頂点を使用して船の形状を定義します:

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); 
} 

によって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を変更するだけで、プレイヤーに船を「アップグレード」させることができます。

+0

'default_shape' - >' default_ship'をしますか? – chux

+1

@chux:良い点、ありがとう!実際には、船の現在の頂点(現在の平行移動と向き)と船の(回転していない、回転していない)形状の違いをOPが確実に理解したいので'default_shape'を使います。私はそれが動作するかどうかわからない(元の/回転していないと現在の/回転と翻訳されたものを区別するのに役立つ)が、私は今できることは最高です。 –

関連する問題