Reputation: 115
I've got a problem - I say problem, it's more of an extreme inconvenience that makes it annoying to play with.
I'm using XNA Monogame to produce a 3D game (A painful job that would be easier in unity but for reasons I can't be bothered to go into, it's not.) and my camera is meant to set the player's mouse to the centre of the window/viewport and then get the change in mouse movement between that and the next frame, which will be used to rotate the camera... It was working... Kind of. But now that I've transferred this project to a PC, rather than a laptop I was working on, the camera has become very choppy when moving. I'm not quite sure how to fix it, I've been messing around with a few of the values in the code snippet I'll post but it just doesn't flow nice anymore. This PC is setup using 3 screens if that could be a problem?
if (moveVector != Vector3.Zero)
{
//Normalise the vector - to stop us moving faster diagonally
moveVector.Normalize();
//Add smooth and speed
moveVector *= deltaTime * cameraSpeed;
//Move camera
Move(moveVector);
}
//Handle mouse movement
float deltaX;
float deltaY;
if (currentMouseState != previousMouseState)
{
//Save mouse location
deltaX = currentMouseState.X - (Game.GraphicsDevice.PresentationParameters.BackBufferWidth / 2);
deltaY = currentMouseState.Y - (Game.GraphicsDevice.PresentationParameters.BackBufferHeight / 2);
//Determines the speed of the rotation 0.1 is pretty quick and looks just about right
mouseRotationBuffer.X -= 0.1f * deltaX * deltaTime;
mouseRotationBuffer.Y -= 0.1f * deltaY * deltaTime;
if (mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
{
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));
}
if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
{
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));
}
Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)),
MathHelper.WrapAngle(mouseRotationBuffer.X), 0);
deltaX = 0;
deltaY = 0;
}
Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
Before anyone says, I'm also posting this to gamedev, but I thought I'd try here too on the off chance someone knows something.
Upvotes: 0
Views: 498
Reputation: 11
You snippet looks fine, however, when you want a smooth rotation of the camera one would adjust to have the values smooth out as they increment or decrement to the new mouse position.
Its something that Unity makes simple of during mouse translations and its transform properties, all you would have to do is Slerp the values for the last position and the new position of the mouse adjusted for the speed of the mouse moving.
Just a little bit of sudeo-code to demonstrate the choppy rotation of a camera.
// This is a potential Unity fix for solving camera translations in general
// for smooth movement
void Update() {
Vector3 msNewPoint = Mouse.Position;
Vector3 adjustedPoint = msOldPoint - msNewPoint;
Vector3 slerpedValue = Vector3.Slerp(msOldPoint, adjustedPoint, 0.2f);
gameObject.Transform.Rotation *= slerpedValue;
}
I stumbled on the same issue with multiple screens, this was a simple fix for me when I clamped the mouse to stay on the viewport of the game itself.
// Again this is sudo code to demonstrate clamping the mouse to prevent multi
// monitor dpi (IF you are using spanned displays.
// Ie nVidia surround, or AMD Eyefinity.
private Rectangle oldClipRect;
private bool oldClipSet;
void clampMouse(Control control) {
Rectangle screenRect = control.RectangleToScreen(control);
// Initialize this only once to prevent the clip being altered
// when the size of the screen changes
if (!oldClipSet) {
oldClipRect = Cursor.Clip;
oldClipSet = true;
}
// If the control is focused bind the mouse to the game screen,
// otherwise release it.
if (control.Focused)
Cursor.Clip = screenRect;
else Cursor.Clip = oldClipRect;
}
Upvotes: 0