如何将光标锁定到游戏窗口?

发布于 2025-01-04 12:39:13 字数 553 浏览 1 评论 0原文

我正在尝试为 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;
}

当鼠标实际上位于窗口内时,这似乎工作得很好,但一旦我离开窗口,它就不起作用了。我认为我必须做的是以某种方式将鼠标限制在窗口内,因为即使当我的鼠标在窗口外时它触发了鼠标移动,并且仍然遇到相同的问题,就在我桌面的边界处坐标代替。

那么...我该怎么做——将鼠标锁定在窗口内?我基本上只是将鼠标位置设置为中心吗?如果是这样...我如何设置鼠标位置?我使用的是 Windows,但如果 OpenTK 提供的话,我更喜欢非本机解决方案。

I'm trying to implement camera movement for an FPS game. I think I've almost got it, but there's just a few more kinks to work out. I've got my mouse movement set up like this:

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;
}

Which seems to work pretty well when the mouse is actually inside the window, but as soon as I leave the window it doesn't work. I think what I have to do is somehow constrain the mouse to be inside the window, because even if it triggered a mouse move when my mouse was outside of the window, and still run into the same issue, just at the bounds on my desktop coords instead.

So...how do I do that -- lock my mouse to inside the window? Do I essentially just keep setting the mouse position to the center? If so...how do I set the mouse position? I'm using Windows, but I'd prefer a non-native solution if OpenTK provides it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

晨与橙与城 2025-01-11 12:39:13

在 OpenTK 3.2 中非常简单

OpenTK.GameWindow window = new OpenTK.GameWindow();
window.CursorGrabbed = true;

您还可以使用此代码片段来隐藏光标。只需根据需要实施即可。

window.Cursor = MouseCursor.Empty;

Quite simple in OpenTK 3.2

OpenTK.GameWindow window = new OpenTK.GameWindow();
window.CursorGrabbed = true;

You can additionally use this snippet to hide the cursor. Just implement it as needed.

window.Cursor = MouseCursor.Empty;
帅气尐潴 2025-01-11 12:39:13

我做过的一个做法,以及旧的《雷神之锤》游戏(以及《半条命 1》)所使用的做法,是在每一帧中将光标位置重置为屏幕中间,然后从屏幕中间计算增量。

编辑:要移动光标,请查看 光标.位置

One practice that I have done, and that the old Quake games used (and half-life 1), is every frame you reset the cursor position to be the middle of the screen, then you calculate the delta from the middle of the screen.

EDIT: And to move the cursor, check out Cursor.Position

零崎曲识 2025-01-11 12:39:13

这是我现在的解决方案...但它特定于 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);
}

This is my solution right now...it's specific to windows though.

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文