私はあなたの数学で見るいくつかの問題:
- あなたがそれらを変更している間、あなたはあなたのポイントを回転しています。これは、
X
が正しく計算されるかもしれないが、新しいY
の計算は、X
の元の値の代わりに新しいX
を使用することを意味する。それは間違っており、新しいポイントを計算するときに古いポイントを保存する必要があります。下記のrotatePoint()
でこれを行う例を見てください。
- 回転するときにピボットポイントを指定する必要があります。これがどのように行われるかは、
rotatePoint
を参照してください。これは投稿されたアルゴリズムhereに基づいています。
cos()
およびsin()
は、角度がラジアン単位であると予想します。すでにshipHeading
でこれを考慮しているかどうかはわかりませんが、int
であるため考えられません。私の解答では、shipHeading
が度であると仮定し、trig関数を呼び出す前にそれをラジアンに変換します。
- ポイントに-1を乗算すると、あなたのトランケーションのアイデアは変わったように見えます。小惑星では、これは現在の速度と加速に基づいてポイントにintを加えるべきです。
アルゴリズムを作成する手順はカプセル化です。すべてのintで1つの関数内のすべてを実行しようとしないでください。 (x、y)のペアを表すPointのような抽象データ型を作成します。
typedef struct {
int x;
int y;
} Point;
次に、3つのポイントで構成される船を表す別の抽象データ型を作成します。
typedef struct {
Point top;
Point left;
Point right;
} Ship;
次に、ピボット点を中心に回転する点を抽象化するヘルパー関数を作成します。次に、ピボットポイントを中心に船を回転させる高水準の関数を作成します。この関数は、3つのポイントのそれぞれを回転するroatePoint関数を呼び出します。
詳細を抽象化することで、アルゴリズムが明確になります。また、バグ修正が多くの代わりに1か所に表示されることを意味します。たとえば、cos()とsin()は回転をRadianで表現すると考えていますが、通常は回転の度合いで考えることができます。回転をPivotPoint()に分離することで、すべての数学がこの1か所に配置されます。ここで
はスタブ不足している機能のいくつかと、私のソリューションです:
#include <stdio.h>
#include <math.h>
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point top;
Point left;
Point right;
} Ship;
// See https://stackoverflow.com/a/2259502/6693299 for point rotation algorithm
Point rotatePoint(Point pivotPoint, Point point, int shipHeading)
{
Point newPoint = {0};
// Translate point back to the origin
point.x -= pivotPoint.x;
point.y -= pivotPoint.y;
// Cos and Sin expect angle in radians, but let's use shipHeading in degrees
// To convert shipHeading in degrees to radians, multiply by 0.0174533
double radians = ((double) shipHeading) * 0.0174533;
// Rotate Point
// Compute new point based on old point and shipHeading
newPoint.x = (point.x * cos(radians)) - (point.y * sin(radians));
newPoint.y = (point.x * sin(radians)) + (point.y * cos(radians));
// Translate the point back
newPoint.x += pivotPoint.x;
newPoint.y += pivotPoint.y;
return newPoint;
}
Ship rotateShip(Ship* ship, int shipHeading)
{
Ship newPosition = {0};
// Rotate ship by shipHeading degrees, centered around top
newPosition.top = rotatePoint(ship->top, ship->top, shipHeading);
newPosition.left = rotatePoint(ship->top, ship->left, shipHeading);
newPosition.right = rotatePoint(ship->top, ship->right, shipHeading);
return newPosition;
}
Point newPoint(int x, int y)
{
Point point = {0};
point.x = x;
point.y = y;
return point;
}
Ship newShip(int shipX, int shipY)
{
Ship newShip = {0};
newShip.top = newPoint(shipX, shipY);
newShip.left = newPoint(shipX + 10, shipY - 5);
newShip.right = newPoint(shipX + 10, shipY + 5);
return newShip;
}
// stubs
int getShipX(void) { return 10;}
int getShipY(void) { return 10;}
int getShipHeading(void) {return 90;} // Expressed in degrees
void drawTriangle(int x1, int y1, int x2, int y2, int x3,
{
// stub
printf("Ship location: (%d,%d) (%d,%d) (%d,%d)\n", x1,y1, x2,y2, x3,y3);
}
void drawShip(void){
Ship ship = newShip(getShipX(), getShipY());
int shipHeading = getShipHeading();
int RED = 0; // stub
drawTriangle(ship.top.x, ship.top.y,
ship.left.x, ship.left.y,
ship.right.x, ship.right.y, RED); //pre rotation
ship = rotateShip(&ship, shipHeading);
#if 0
// Multiplying by -1 will Flip the ship?
// Use += instead to move the ship up by one
// Better to use a function like moveShip()
ship.top.x += -1;
ship.top.y += -1;
ship.left.x += -1;
ship.left.y += -1;
ship.right.x += -1;
ship.right.y += -1;
#endif
drawTriangle(ship.top.x, ship.top.y,
ship.left.x, ship.left.y,
ship.right.x, ship.right.y, RED); //pre rotation
}
int main(int argc, char** argv)
{
drawShip();
}
出力は最初、私は(10,10)にデフォルト設定された(右)(左)船の三点(トップ)が表示されます画面の左上部分が(0,0)であるXウィンドウ記法(X、Y)を使用して、(20,5)(20,15) 2番目の出力行は、90度回転した後の点です(10,10)。ピボットポイントを選択できます。ポイントローテーションの詳細については、this stackOverflowの記事を参照してください。
scott> gcc asteroids.c -lm
scott> a.out
Ship location: (10,10) (20,5) (20,15)
Ship location: (10,10) (14,20) (5,19)
scott>
これは出発点として役立ちます。フレームワークに合わせて変更します。