Hello i'm developing a game in c# monogame and having issues with resetting the camera back to behind the player.
When the player holds left click he's able to orbit the camera around his character. When he moves forward the camera resets back behind him slowly. The rotation should decide whether it should rotate left or right around the player to behind the player (the shortest path). At the moment it sometimes orbits the long way around the player and worst of all the currentY will be stuck in-between 1 and -1 and keep moving back and forth really quick like its stuck.
double targetY; //this is the radians Y our camera is going to slowly rotate to
double currentY; //this is our current camera radians Y
float rotateSpeed = 5; //this value lets us slow down how fast we rotate towards targetY
double direction = Math.Cos(targetY) * Math.Sin(currentY) - Math.Cos(currentY) * Math.Sin(targetY);
double distance = Math.Min(currentY - targetY, (MathHelper.Pi * 2) - currentY - targetY);
if (direction > 0)
{
//rotating left towards targetY
currentY -= distance / rotateSpeed;
}
else
{
//rotating right towards targetY
currentY = distance / rotateSpeed;
}
I figure its a problem with not using Math.PI to figure out if it should rotate left or right, but I haven't been able to solve it.
Thank you.
Update:
So I been busy trying to solve this and I figured I already know the target rotation with targetY so I just make currentY slowly rotate to targetY using the code below.
if (currentY < targetY)
{
//simply add currentY by the distance between currentY and targetY / divide it by how slow you want to rotate.
currentY = (targetY - currentY) / rotateSpeed;
}
if (currentY > targetY)
{
//simply minus currentY by the distance between currentY and targetY / divide it by how slow you want to rotate.
currentY -= Math.Abs(targetY- currentY) / rotateSpeed;
}
This new code works fine the only issue is that if the player spins around allot then I let the camera go behind the player after he was spinning the camera spins around the same amount of times until it reaches the players rotation. I think to solve this i need to limit the player and the cameras rotation in-between 0 radians and 6.28319 radians but then the new code above wont work because it has to deal with moving from 6.28319 to 0 and this would break it.
Thank you.
Update #2
Still busy trying this out so far the new code now correctly rotates between 360 degrees and 0 degrees. But now I need to make it work for 180 degrees at the moment the camera will rotate from 170 degrees to -190 (making the camera 360 rotate a full 360 degrees to the other side) instead it should rotate from 170 degrees to 160 degrees while also still rotating from 360 degrees to 0 degrees, here is my code so far.
float newRotation = targetY;
if (targetY < MathHelper.ToRadians(180) && currentY > MathHelper.ToRadians(180))
{
newRotation = targetY MathHelper.ToRadians(360);
}
if (targetY > MathHelper.ToRadians(180) && currentY < MathHelper.ToRadians(180))
{
newRotation = targetY - MathHelper.ToRadians(360);
}
if (currentY < newRotation)
{
currentY = (newRotation - currentY) / rotateSpeed;
}
if (currentY > newRotation)
{
currentY -= Math.Abs(newRotation - currentY) / rotateSpeed;
}
Thank you.
CodePudding user response:
I solved the problem the code below will rotate between 360 degrees and 0 degrees, it also rotates between 170 degrees to 160 degrees, only posting incase it helps someone else.
float newRotation = targetY;
if (targetY < MathHelper.ToRadians(90) && currentY > MathHelper.ToRadians(270))
{
newRotation = targetY MathHelper.ToRadians(360);
}
if (targetY > MathHelper.ToRadians(270) && currentY < MathHelper.ToRadians(90))
{
newRotation = targetY - MathHelper.ToRadians(360);
}
if (currentY < newRotation)
{
currentY = (newRotation - currentY) / rotateSpeed;
}
if (currentY > newRotation)
{
currentY -= Math.Abs(newRotation - currentY) / rotateSpeed;
}
I also stopped the player from constantly increasing or decreasing his degrees as he spins around by using the below code for both the camera and the player.
if (currentY >= MathHelper.Pi * 2) currentY = 0.0f;
if (currentY < 0) currentY = MathHelper.Pi * 2;