【问题标题】:How to make the cursor encaged in an area of my window如何使光标嵌入我的窗口区域
【发布时间】:2015-10-23 17:27:23
【问题描述】:

我想要实现的是让我的游戏光标停留在我窗口的“游戏”区域,因此用户无法将光标移出这些界限。我不希望光标停留在一个位置,我仍然希望用户能够四处移动鼠标并单击,我只是希望鼠标被“锁定”在一个区域中。请看这个演示:

Game screenshot for demonstration

我希望光标停留在我制作的粉红色标记之外的绿色框中。 所以我听说有一种方法可以通过在java中使用“Robot”或将MouseGrabbed设置为true来实现,但是没有找到足够的教程,所有测试都失败了。

总的来说,我对 Slick2D 和 java 游戏开发还很陌生,所以请非常具体并指导我完成您的想法。 提前致谢!

【问题讨论】:

    标签: java window mouse lwjgl slick2d


    【解决方案1】:

    如果我对您的理解正确,您需要以下内容:

    1. 将光标限制在屏幕截图下方的绿色框内
    2. 在游戏窗口外导航时仍允许原生光标可用(未抓取)(即用户可以单击 x 按钮等)

    我之前通过渲染我自己的光标并在游戏窗口中隐藏本机光标来实现这一点。有几个步骤可以做到这一点。我应该提到,这是使用比当前 LWJGL 产品稍旧的版本完成的,我不确定您运行的是哪个版本。

    第 1 步:禁用本机光标

    您想在游戏窗口内禁用本机光标。在我的情况下,抓取过于激进,因为它完全禁用了窗口游戏的鼠标。初始化游戏时,请尝试以下操作:

        try {
            final Cursor emptyCursor = new Cursor(1, 1, 0, 0, 1, BufferUtils.createIntBuffer(1), null);
            Mouse.setNativeCursor(emptyCursor);
        } catch (final LWJGLException e) {
            //TODO: Consider better exception handling
            e.printStackTrace();
        }
    

    它的作用是在您的游戏窗口中将本机鼠标渲染为空。这意味着当您将鼠标悬停在游戏上时,您通常看到的箭头会消失。这并不意味着鼠标不起作用,我们只是将它隐藏了。

    第 2 步:在收集键盘/鼠标输入时跟踪鼠标移动

    public void collectInput() {
        while(Mouse.next()){
            this.mouseX = Mouse.getX();
            final int newMousePosition = Mouse.getY();
    
            //Only move the cursor on the Y axis if it is between the upper and lower bounds
            if(newMousePosition < this.upperBound && newMousePosition > this.lowerBound){
                this.mouseY = newMousePosition;
            }
            this.mouseY = Display.getHeight()- Mouse.getY();
            //TODO: Consider adding logging here
        }
    }
    

    我有一个 collectInput() 方法,可以抓取我认为必要的按键/鼠标事件。我在这里所做的只是在我的游戏窗口中抓取鼠标的当前 X/Y。从总显示高度中减去 Y 坐标,以便稍后处理渲染坐标与鼠标坐标。就我而言,我只是使用了整个窗口的边界,但如果 X/Y 坐标超出了您的绿色框,您可能需要考虑不更新它们。

    编辑 根据您的评论,如果新坐标不在某些边界内,我在此处更新了代码块以不更新 Y 坐标。您需要确定 x 和 y 边界是什么,并且仅当从 Mouse 类收集的新坐标位于其中时才更新鼠标 X/Y 坐标。

    第 3 步:渲染您自己的光标

    最后,您需要渲染光标。这看起来就像您将使用 LWJGL 进行的任何其他渲染。我的示例假设您对此有纹理:

    //Render mouse texture
        Color.white.bind();
        this.mouseTexture.bind();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex2f(this.mouseX, this.mouseY);
        GL11.glTexCoord2f(1, 0);
        GL11.glVertex2f(this.mouseX + this.cursorHeight, this.mouseY);
        GL11.glTexCoord2f(1, 1);
        GL11.glVertex2f(this.mouseX + this.cursorHeight, this.mouseY + this.cursorWidth);
        GL11.glTexCoord2f(0, 1);
        GL11.glVertex2f(this.mouseX, this.mouseY + this.cursorWidth);
        GL11.glEnd();
        GL11.glDisable(GL11.GL_TEXTURE_2D);
    

    这导致当我在游戏窗口中使用鼠标时,会呈现我的自定义光标。很难从图像中分辨出来,但白色圆圈现在是我的光标,它会随着我移动鼠标而移动。需要注意的是,由于第 1 步,没有显示常规本机光标:

    但是当我离开游戏窗口时,会显示本机鼠标,并且我的自定义光标留在它收到输入的最后一个位置:

    【讨论】:

    • 当,非常感谢您的彻底回答。我以您的想法为例,并对其进行了改造以适应我的需要。所以我所做的就是从网络上抓取一个 32x32 的光标,用 Slick2D 将它加载到我的程序中,抓住鼠标使其消失,然后用 Mouse.getX(); 将光标图像绑定到鼠标坐标等等。所以现在,光标是我的“鼠标”,它永远不会离开窗口,因为它是一个图像。我现在的问题是:如何让光标图像不超出下方的绿色矩形?因为它可以通过带有红心等的绿色上部绿色条带,这是一个诺诺。
    • 添加到答案中以显示如何执行此操作。您只需要建立一些边界并在更新 x/y 坐标时检查它们。如果移动到的鼠标位置超出您的边界(在您的情况下为绿色框),请不要重新分配 mouseX 和/或 mouseY。
    • 非常感谢!那么,在我的 Slick2D 游戏状态下,我会将您的块放置在第 2 步的什么位置呢? (初始化?渲染?更新?)最后一个问题,有点跑题了,但是你知道如何切换鼠标方向来反转吗?例如,如果用户将鼠标向左移动,则光标向右移动,如果向上移动,光标向下等。如果您无法回答,那很好!但这是我的最终目标,我正在努力收集尽可能多的信息。
    • 很难说没有看到任何代码,但很可能它在你的游戏状态类中。我假设那是您收集鼠标/键盘输入的地方。但不确定其他部分。
    猜你喜欢
    • 1970-01-01
    • 2013-12-04
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 2016-03-29
    相关资源
    最近更新 更多