Search code examples
c#mathcamerarotationmonogame

c# monogame how to make camera reset position slowly behind player


Hello I'm trying to create a sort of MMO camera style where a player can drag to look around the character and when he moves forward the camera slowly rotates back to behind the player, when the camera resets back it choose to move left or right side of the player which ever is shortest path. At the moment the code below is not working for when you need to rotate past 360 degrees to 0 degrees.

[example of working][1]
[example of working][2]
[example of not working][3]

[1]: https://i.sstatic.net/LblS0.png
[2]: https://i.sstatic.net/ujiSs.png
[3]: https://i.sstatic.net/zpHGE.png
float yMaxRotation; //is our target rotation (our Green Pointer)
float yRotation; //is our camera rotation (our Grey Pointer)

yMaxRotation = target.rotation.Z - (MathHelper.PiOver2);
yMaxRotation = yMaxRotation % MathHelper.ToRadians(360);
if (yMaxRotation < 0) yMaxRotation += MathHelper.ToRadians(360);

float newRotation = yMaxRotation;

if (yMaxRotation <= MathHelper.ToRadians(90) && yRotation >= MathHelper.ToRadians(270))
{
    newRotation = yMaxRotation - MathHelper.ToRadians(360);
}
if (yMaxRotation >= MathHelper.ToRadians(270) && yRotation <= MathHelper.ToRadians(90))
{
    newRotation = yMaxRotation + MathHelper.ToRadians(360);
}

if (yRotation <= newRotation)
{
    yRotation += (newRotation - yRotation) / 15;
}
if (yRotation > newRotation)
{
    yRotation -= Math.Abs(newRotation - yRotation) / 15;
}

And for the camera handling the distance and its direction it calls this code every update

Position //is our cameras position
newPos //is our players character position - the offset (push camera back and up)

Vector3 newPos = ((target.position - target.positionOffset) + new Vector3(0, 0, 18));
SetLookAt(Position, newPos, Vector3.Backward);

Solution

  • The math when comparing angles does not equate the distance between 1 and 359 as 2.

      float yMaxRotation; //is our target rotation (our Green Pointer)
      float yRotation; //is our camera rotation (our Grey Pointer)
    
      yMaxRotation = target.rotation.Z - MathHelper.PiOver2; // Copied from source.
    
    
      float newRotationDelta = (yMaxRotation - yRotation - MathHelper.Pi - 
    
                 MathHelper.TwoPi) % MathHelper.TwoPi + MathHelper.Pi; // scale -179 to 180
      
      yRotation += newRotationDelta / 15;
    
    

    The yMaxRotation - yRotation gets the delta angle. Subtract 540(180 + 360 or any multiple of 360 since the mod removes it, to make sure the value is negative) to create a negative x-axis reflected angle modded to the range (-359 to 0) and then adds back 180 to reverse the reflection and recenter on zero.