如何通过计算新的x和y位置围绕精灵的中心旋转精灵? 我使用黑暗GDK和C++来创建一个简单的2D游戏。我正在旋转一个对象,但它从精灵的左上角旋转

如何通过计算新的x和y位置围绕精灵的中心旋转精灵? 我使用黑暗GDK和C++来创建一个简单的2D游戏。我正在旋转一个对象,但它从精灵的左上角旋转,c++,C++,我有以下可用变量: PlayerX 游戏 游戏者宽度 演奏家 旋转角度(360>x>0) 是否有一种算法可以修改精灵的轴心点,而不是中心 下面是一个小代码示例: void Player::Move( void ) { if ( checkLeft() ) { PlayerX -= PlayerSpeed; if ( PlayerX < 0 ) PlayerX = 0; } if ( checkR

我有以下可用变量:

  • PlayerX
  • 游戏
  • 游戏者宽度
  • 演奏家
  • 旋转角度(360>x>0)
是否有一种算法可以修改精灵的轴心点,而不是中心

下面是一个小代码示例:

void Player::Move( void )
{

    if ( checkLeft() )
    {
        PlayerX -= PlayerSpeed;
        if ( PlayerX < 0 )
            PlayerX = 0;
    }

    if ( checkRight() )
    {
        PlayerX += PlayerSpeed ;
        if ( PlayerX > 800 - PlayerWidth )
            PlayerX = 800 - PlayerWidth;
    }

    if ( checkUp())
    {
        PlayerY -= PlayerSpeed;
        if ( PlayerY < 0 )
            PlayerY = 0;
    }

    if ( checkDown())
    {
        PlayerY += PlayerSpeed;
        if ( PlayerY > 600 -  PlayerHeight)
            PlayerY = 600 - PlayerHeight;
    }

    RotateAngle += 5;
    if(RotateAngle > 360)
        RotateAngle -=360;

    dbRotateSprite(Handle,RotateAngle);
    dbSprite ( 1 , PlayerX , PlayerY , Handle );
}
void播放器::移动(void)
{
if(checkLeft())
{
PlayerX-=玩家速度;
如果(PlayerX<0)
PlayerX=0;
}
if(checkRight())
{
PlayerX+=玩家速度;
如果(PlayerX>800-PlayerWidth)
PlayerX=800-PlayerWidth;
}
if(checkUp())
{
PlayerY-=玩家速度;
if(PlayerY<0)
PlayerY=0;
}
if(checkDown())
{
PlayerY+=玩家速度;
如果(播放器>600-播放器高度)
PlayerY=600——演奏者的高度;
}
旋转角度+=5;
如果(旋转角度>360)
旋转角度-=360;
dbRotateSprite(手柄,旋转角度);
dbSprite(1,PlayerX,PlayerY,Handle);
}
编辑

我正在考虑为这个问题打开一些名声,我还没有得到一个适合我的答案。如果有人能提供一个实际的代码样本来完成这项工作,我将非常高兴

Blindy的答案的问题是,无论我如何简单地来回翻译,尖塔仍然围绕左上角旋转,并移动到某个地方围绕左上角旋转,然后将其移回相同的位置,都不会产生任何效果。以下是我认为正在发生的事情:

只是为了不让人感到困惑,我创造了一个正在发生的事情的图像。左边显示实际发生的事情,右边显示我需要发生的事情


您需要执行以下操作:

  • 翻译为(-
    playerx
    -
    playerwidth
    /2,-
    playery
    -
    playerheight
    /2)
  • 旋转角度
    rotateangle
  • 通过(
    playerx
    +
    playerwidth
    /2,
    playery
    +
    playerheight
    /2)翻译
想法是将精灵居中放置在原点上,然后围绕原点旋转(
glRotate
),在获得旋转的精灵后,将其转换回原来的位置


注意:如果精灵最初围绕原点“居中”,但有一个角不是精灵的实际中心,则首先将对象平移到精灵中心与原点的中心。因此,如果你的精灵在原点的左上角,你将平移(-playerwidth/2,-playerheight/2),然后旋转,然后平移(playerx,playery)。

看着你的图像,你所做的是在原地旋转正方形,你根本没有平移它。这就是你正在做的:

^                         ^
|                         |
|                         |
|               ====>     |
|                         |
+--+----->                x---------->
|  |                     / \
+--+                     \ /
                          x
如您所见,正方形的左上角位于原点,您所做的只是围绕原点旋转

这就是我说的你应该做的:

^                         ^                ^
|                         |                |
|                         |        ===>    |     ==> translate to
|               ====>     |                x     ==> where you want
|                        +-+              /|\    ==> to draw it
+--+----->               |+|--------->     +-------->
|  |                     +-+              \ /
+--+                                       x

只能围绕中心旋转,因此将要旋转基本体的点居中,然后将它们放置在所需的位置。

旋转对象时,将对构成对象的点应用变换。在本例中,四个角各自独立旋转,最终结果是在其新位置形成四边形。正如其他人所提到的,关键的部分是知道点旋转的原点在哪里

想象一下,如果不是精灵,你只有一个点。如果其原点与该点位于同一位置,则旋转该点不会产生任何效果(该点的位置不会移动)。但是,如果原点位于其他任何位置,则该点将以原点为圆心在圆中旋转。你怎么能让原点不在点的同一位置?在坐标系内移动点。换句话说,翻译它

各种变换(旋转、平移、缩放等)的顺序对此至关重要。如果将点旋转180度,然后将其向右平移,则该点将位于其开始位置的右侧,但如果将其向右移动,然后将其旋转180度,则该点将位于左侧


我建议大家阅读2D变换。了解矩阵在所有这些方面的作用也会很有用,但这并不是获得所需效果的必要条件。

到目前为止,答案在告诉您应该如何实现这一点上是正确的,但我担心黑暗的GDK API似乎太原始,无法以这种简单的方式实现

不幸的是,
dbRotateSprite
将精灵旋转到左上角,而不考虑精灵的变换,这就是为什么您对其他建议没有把握的原因。要模拟围绕中心旋转,您必须手动更正精灵的位置,即您只需旋转精灵,然后将其作为两步过程移动

我不熟悉API,我不知道y是向上还是向下测量,角度是以哪种方式测量的,所以我要做一些假设。如果y像许多其他2D图形系统一样向下测量,并且随着x轴从正x轴到正y轴的增加,从x轴开始测量角度,那么我相信正确的psuedo代码如下所示

// PlayerX and PlayerY denote the sprite centre
// RotateAngle is an absolute rotation i.e. not a relative, incremental rotation

RotateAngle += 5;
RotateAngle %= 360;
RadiansRotate = (RotateAngle * PI) / 180;

dbRotateSprite( Handle, RotateAngle );

HalfSpriteWidth = dbSpriteWidth( Handle ) / 2;
HalfSpriteHeight = dbSpriteHeight( Handle ) / 2;

SpriteX = PlayerX
        - HalfSpriteWidth * cos(RadiansRotate)
        + HalfSpriteHeight * sin(RadiansRotate);
SpriteY = PlayerY
        - HalfSpriteHeight * cos(RadiansRotate)
        - HalfSpriteWidth * sin(RadiansRotate);

// Position the top left of the sprite at ( SpriteX, SpriteY )
dbSprite ( 1 , SpriteX , SpriteY , Handle );

天哪,我已经试着这么做了一段时间了,我找到了这一页,只是复制一下。 这是基于以前的一篇文章

void dbRotateSpriteCenter(int iID, int iX, int iY, int fRotate, int iImage)
{
int x = iX 
    - dbSpriteWidth(iID) / 2 * cos(fRotate * 3.1415926536 / 180) 
    + dbSpriteHeight(iID) / 2 * sin(fRotate * 3.1415926536 / 180);
int y = iY 
    - dbSpriteHeight(iID) / 2 * cos(fRotate * 3.1415926536 / 180)
    - dbSpriteWidth(iID) / 2 * sin(fRotate * 3.1415926536 / 180);
dbRotateSprite(iID, fRotate);
dbSprite(iID, x, y, iImage);
}

您可以使用dbOffsetSprite()

创建精灵时,其插入点默认为左上角(dbRotateSprite();围绕插入点旋转精灵),可以使用此功能