如何通过计算新的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
/2,-playerwidth
-playery
/2)playerheight
- 旋转角度
rotateangle
- 通过(
+playerx
/2,playerwidth
+playery
/2)翻译playerheight
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();围绕插入点旋转精灵),可以使用此功能