我正在尝试为FPS游戏实现相机移动。我想我差不多了,但还有一些问题需要解决。我的鼠标移动设置如下:
protected override void OnLoad(EventArgs e)
{
Mouse.Move += OnMouseMove;
}
void OnMouseMove(object sender, MouseMoveEventArgs e)
{
_lookDir.X += e.XDelta * _mouseSensitivity;
_lookDir.Y -= e.YDelta * _mouseSensitivity;
}
当鼠标实际上在窗口内时,这似乎工作得很好,但是一旦我离开窗口它就不起作用。我认为我要做的就是以某种方式将鼠标限制在窗口内部,因为即使它在我的鼠标位于窗口之外时触发了鼠标移动,仍然遇到同样的问题,只是在桌面上的界限而不是coords。
那么......我该怎么办 - 将鼠标锁在窗户内?我基本上只是将鼠标位置设置在中心位置吗?如果是这样......我该如何设置鼠标位置?我正在使用Windows,但如果OpenTK提供它,我更喜欢非原生解决方案。
答案 0 :(得分:2)
我所做的一个练习,以及旧的Quake游戏(和半衰期1),是你将光标位置重置为屏幕中间的每一帧,然后你从中间计算增量屏幕。
编辑:要移动光标,请查看Cursor.Position
答案 1 :(得分:2)
在OpenTK 3.2中非常简单
OpenTK.GameWindow window = new OpenTK.GameWindow();
window.CursorGrabbed = true;
您还可以使用此代码段隐藏光标。只需根据需要实施即可。
window.Cursor = MouseCursor.Empty;
答案 2 :(得分:1)
这是我现在的解决方案......但它特定于Windows。
protected void ResetCursorPosition()
{
Cursor.Position = WindowCenter;
_lastMousePos = Cursor.Position;
}
protected void LockMouse()
{
_lockMouse = true;
_origCursorPosition = Cursor.Position;
CursorVisible = false;
ResetCursorPosition();
}
protected void UnlockMouse()
{
_lockMouse = false;
CursorVisible = true;
Cursor.Position = _origCursorPosition;
}
void OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (!_lockMouse) LockMouse();
}
void OnKeyDown(object sender, KeyboardKeyEventArgs e)
{
if(e.Key == Key.Escape)
{
if (_lockMouse) UnlockMouse();
else Exit();
}
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
Title = string.Format("{0} - {1:0.0} FPS", _windowTitle, RenderFrequency);
float moveSpeed = Keyboard[RunKey] ? 0.9f : 0.4f;
if (Keyboard[MoveForwardKey])
{
_pos.X += (float)Math.Cos(_lookDir.X) * moveSpeed;
_pos.Z += (float)Math.Sin(_lookDir.X) * moveSpeed;
}
if (Keyboard[StrafeLeftKey]) // FIXME: holding W + A gives extra speed (also, perhaps strafing should be slower?)
{
_pos.X -= (float) Math.Cos(_lookDir.X + Math.PI / 2) * moveSpeed;
_pos.Z -= (float) Math.Sin(_lookDir.X + Math.PI / 2) * moveSpeed;
}
if (Keyboard[StrafeRightKey])
{
_pos.X += (float)Math.Cos(_lookDir.X + Math.PI / 2) * moveSpeed;
_pos.Z += (float)Math.Sin(_lookDir.X + Math.PI / 2) * moveSpeed;
}
if (Keyboard[MoveBackKey])
{
_pos.X -= (float)Math.Cos(_lookDir.X) * moveSpeed;
_pos.Z -= (float)Math.Sin(_lookDir.X) * moveSpeed;
}
if(Keyboard[JumpKey])
{
_pos.Y += moveSpeed;
}
if (Keyboard[CroucKey])
{
_pos.Y -= moveSpeed;
}
if (_lockMouse)
{
var mouseDelta = Cursor.Position - new Size(_lastMousePos);
if (mouseDelta != Point.Empty)
{
_lookDir.X += mouseDelta.X * _mouseSensitivity;
_lookDir.Y -= mouseDelta.Y * _mouseSensitivity;
ResetCursorPosition();
}
}
var target = _pos + new Vector3((float)Math.Cos(_lookDir.X), (float)Math.Sin(_lookDir.Y / 2), (float)Math.Sin(_lookDir.X));
_viewMat = Matrix4.LookAt(_pos, target, _up);
_projUniform.Mat4(_viewMat * _projMat);
}