【问题标题】:Custom C++ 2D game engine: Problems translating sprite screen location relative to camera rotation自定义 C++ 2D 游戏引擎:转换精灵屏幕位置相对于相机旋转的问题
【发布时间】:2021-04-03 22:59:23
【问题描述】:

我正在从头开始创建一个 2D C++ 游戏引擎,减去直接调用操作系统。为此,我正在使用 SFML。我基本上只是使用 SFML 来绘制屏幕并收集输入,因此我不会寻求任何与 SFML 相关的帮助。

现在,我可以上下平移相机,并且精灵可以正确地从世界坐标转换为屏幕坐标。在大多数情况下,精灵还会将屏幕坐标从世界坐标转换为相对于相机旋转的坐标。当渲染的游戏对象具有比相机更高的 y 世界坐标时,问题就出现了。发生这种情况时,精灵会出现在 x 轴上。

我会注意到,如果我注释掉下面显示的轮换代码,则不会发生这种情况。

    //shape's position has been set relative to camera position first
    
    Vector2 screenCenter(windowWidth / 2, windowHeight / 2);
    Vector2 shapePosition = shape->GetPosition ();

    //create vector from center screen to shape position
    Vector2 relativeVector = shapePosition - screenCenter;

    float distance = relativeVector.Magnitude ();
    if ( distance == 0 ) { return;  }

    float angle = Vector2::AngleInRads ( Vector2 ( 1, 0 ), relativeVector );

    //rotation of camera in radians
    float targetRotation = camera.GetFollowTarget ()->GetTransform ().GetRotation() * (M_PI / 180);

    //combine rotation of camera and relative vector
    float adjustedRotation = angle + targetRotation;

    //convert rotation into a unit vector
    Vector2 newPos ( cos ( adjustedRotation ), sin ( adjustedRotation ) );

    //extend unit vector to be the same distance away from the camera
    newPos *= distance;

    //return vector origin to screen center
    newPos += screenCenter;

    shape->SetPosition ( newPos );

以下是一些截图。

您可以将蓝色方块视为我相机的焦点。 紫色圆圈是 (0,0) 世界坐标 箭头在世界空间中指向上方,如您所见,当相机位于其下方时,其渲染不正确。

很难展示轮换的实际效果,因此您必须相信我的话。除了我所描述的之外,旋转在相机的任何位置都按预期工作。

View while camera is at origin

View while camera is at the mid point of arrow

View while camera is above arrow

如果还有什么我可以提供的有用的,请告诉我。

【问题讨论】:

  • 你似乎没有使用sf::View's,我会推荐他们。 sfml-dev.org/tutorials/latest/graphics-view.php
  • 感谢您的评论,但我正在尝试从头开始挑战自己,以加深对图形相关概念的理解。
  • 我明白了。然后我会了解变换矩阵,这些可以将平移、旋转和缩放应用于点或另一个变换矩阵。如果您可以将您的视图表示为转换矩阵(您应该可以),并将您的精灵表示为转换矩阵(您应该可以),那么您可以将它们相乘以获得您正在寻找的结果。我相信这就是大多数游戏引擎的做法,这就是我仅使用 OpenGL 的做法以及 SFML 至少是这样做的。
  • 对于 OpenGL 中的变换或变换背后的一般数学,我最近使用了 LearnOpenGL 的变换页面。可能有更好的指南,但由于我一直在学习更现代的 OpenGL,这是我目前的建议。一旦你知道了它的操作,实现你自己的 Matrix 类就很容易了。要坚持使用 SFML,请查看它的源代码,特别是 View.cpp 中的 View::getTransform()Transformable.cpp 中的 Transformable::getTransform()Transform.cpp 中的 Transform::combine()

标签: c++ rendering game-engine sfml


【解决方案1】:

我突然想到将这个问题作为数学问题而不是编程问题在谷歌上搜索。

我的问题的解决方案可以在这里找到。 Solution

    Vector2 shapePos = shape->GetPosition ();

    //subtract screen center from point
    shapePos.x -= windowWidth/2;
    shapePos.y -= windowHeight/2;

    float angleInRadians = camera.GetFollowTarget ()->GetTransform ().GetRotation () * ( M_PI / 180 );

    //Get coordinates after rotaion
    float x = ( shapePos.x * cos ( angleInRadians ) ) - ( shapePos.y * sin ( angleInRadians ) );
    float y = ( shapePos.x * sin ( angleInRadians ) ) + ( shapePos.y * cos ( angleInRadians ) );

    //add screen center back to point
    Vector2 newPos ( x + windowWidth/2, y + windowHeight/2 );
    shape->SetPosition ( newPos  );

【讨论】:

    猜你喜欢
    • 2016-11-02
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多