0

I am creating a 2D C++ game engine from scratch minus making calls to the OS directly. For that, I am using SFML. I am essentially only using SFML to draw to the screen and collect input, so I am not looking for help with anything related to SFML.

Right now, I can pan the camera up and down and the sprites translate from world coordinates to screen coordinates correctly. The sprites also, for the most part, translate screen coordinates from world coordinates relative to camera rotation. The problem comes in when a rendered game object has a higher y world coordinate than the camera. When this happens it would appear that the sprite is reflected on the x-axis.

I will note that this does not happen if I comment out the rotation code shown below.

    //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 );

Below are some screenshots.

You can consider the blue square as my camera's focus. The purple circle is (0,0) world coordinates The arrow is pointing up in world space and as you can see is rendered incorrectly while the camera is below it.

It would be hard to show the rotation in action so you'll have to take my word for it. The rotation works as intended at any position of the camera aside from what I've described.

View while camera is at origin

View while camera is at the mid point of arrow

View while camera is above arrow

Please let me know if there's anything else I can provide that would be helpful.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    You do not seem to be using `sf::View`'s, I would recommend them. https://www.sfml-dev.org/tutorials/latest/graphics-view.php – Lily Apr 04 '21 at 08:30
  • Thank you for your comment but, I am trying to do this from scratch to challenge myself to deepen my understanding of graphics-related concepts. – gBrandt Apr 04 '21 at 16:44
  • I see. I would learn about Transformation Matrices then, these can apply a Translation, Rotation and Scale to points or another Transformation Matrix. If you can represent your view as a transformation matrix (you should be able to), and represent your sprite as a transformation matrix (you should be able to), then you can multiply them together to get the result you are looking for. I believe this is how most game engines do it, this is how I do it with just OpenGL and how SFML does it at least. – Lily Apr 04 '21 at 17:26
  • For Transforms in OpenGL or just the general maths behind Transforms I have most recently used LearnOpenGL's page on Transformations. There might be better guides, but since I have been learning more modern OpenGL this is my current recommendation. It's pretty easy to implement your own Matrix class once you know its operations. To stick with SFML, check out it's source code, specifically `View::getTransform()` in `View.cpp`, `Transformable::getTransform()` in `Transformable.cpp` and `Transform::combine()` in `Transform.cpp`. – Lily Apr 04 '21 at 17:26

1 Answers1

0

It dawned on me to google this problem as a math problem more than a programming problem.

The solution to my problem can be found here. 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  );