我试图重新创建游戏小行星,而我现在正在让船显示并在屏幕上移动。目前我已经获得了下面的功能,它在屏幕上围绕原点绘制一个三角形。我想要做的就是绕着原点旋转船。
此时三角形被这个功能完全扭曲了,我不知道出了什么问题。我尝试旋转的角度是shipHeading
,我试图遵循这个公式:
x' = x cos f - y sin f
y' = y cos f + x sin f
其中f等于旋转角度
void drawShip(void){
int shipX = getShipX();
int shipY = getShipY();
int shipHeading = getShipHeading();
int x1, y1, x2, y2, x3, y3;
x1 = shipX;
y1 = shipY - 20;
x2 = shipX - 10;
y2 = shipY + 10;
x3 = shipX + 10;
y3 = shipY + 10;
screen->drawTriangle(x1, y1, x2, y2, x3, y3, RED); //pre rotation
x1 = (x1 * cos(double(shipHeading))) - (y1 * sin(double(shipHeading)));
y1 = (x1 * sin(double(shipHeading))) + (y1 * cos(double(shipHeading)));
x2 = (x2 * cos(double(shipHeading))) - (y2 * sin(double(shipHeading)));
y2 = (x2 * sin(double(shipHeading))) + (y2 * cos(double(shipHeading)));
x3 = (x3 * cos(double(shipHeading))) - (y3 * sin(double(shipHeading)));
y3 = (x3 * sin(double(shipHeading))) + (y3 * cos(double(shipHeading)));
x1 *= -1;
y1 *= -1;
x2 *= -1;
y2 *= -1;
x3 *= -1;
y3 *= -1;
screen->drawTriangle(x1, y1, x2, y2, x3, y3, BLUE); //post rotation
答案 0 :(得分:3)
问题似乎与在旋转期间覆盖x1,y1,...有关。 介绍坐标的后转换版本,它可能会更好。
答案 1 :(得分:0)
我在数学中看到的一些问题:
X
,但新Y
的计算将使用新的X
而不是X
的原始值。这是错误的,你需要在计算新点时保存旧点。请参阅下面的rotatePoint()
中执行此操作的示例。rotatePoint
以了解如何完成此操作。这基于发布的here算法。cos()
和sin()
期望角度为弧度单位。不确定您是否已将shipHeading
考虑在内,但似乎不太可能,因为它是int
。在我的解决方案中,我假设shipHeading
是度,并在调用trig函数之前将其转换为弧度。创建算法的步骤是封装。不要尝试使用所有整数在一个函数中执行所有操作。创建像Point这样的抽象数据类型来表示(x,y)对。
typedef struct {
int x;
int y;
} Point;
然后创建另一个名为Ship的抽象数据类型来表示由三个点组成的船。
typedef struct {
Point top;
Point left;
Point right;
} Ship;
接下来,创建一个辅助函数来抽象枢轴点周围的旋转点。然后创建一个高级函数,围绕一个枢轴点旋转船,调用roatePoint函数旋转其三个点中的每一个。
通过抽象细节,算法变得清晰。它还意味着错误修复显示在一个地方,而不是很多。例如,cos()和sin()期望旋转以Radians表示,但我们通常根据旋转度来编码思考。通过将旋转隔离到PivotPoint(),所有数学都位于这一个位置。
这是我的解决方案,其中包含几个缺失的函数:
#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();
}
输出首先显示船的三个点(顶部)(左)(右),我使用X窗口符号(X,Y)默认为(10,10)(20,5)(20,15)屏幕的左上部分是(0,0)。第二行输出是围绕顶点(10,10)旋转90度后的点。您可以选择任何支点。有关Point Rotation的更多信息,请参阅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>
希望这有助于作为一个起点。进行更改以适应您的框架。