【问题标题】:Mouse movement optimizations鼠标移动优化
【发布时间】:2009-10-28 17:48:23
【问题描述】:

我想要一个游戏,当鼠标到达窗口的外边缘时,视图会四处移动(类似于许多 RTS 游戏)。我读到使用 MouseMotionListener 时会有很大的开销。

是否有一种方法可以在游戏窗口 (JPanel) 中添加第二个透明组件,它不会影响游戏,但会在鼠标通过 MouseAdapter.mouseEntered()/mouseExited() 离开内部组件时注册?

boolean mouseOnScreen;
boolean mouseWithinInnerComponent; //is (10 <= mouse.x <= screenWidth - 10) && (10 <= mouse.y <= screenHeight)

if(mouseOnScreen && !mouseWithinInnerComponent)
{
    //do something...
}

我不知道如何确定越过哪个屏幕边界,而不必让上述四个组件在角落重叠以在屏幕周围形成边框,从而可以检测鼠标是否在任何边缘或角落.我认为这相当昂贵(必须在运行游戏时检查每个组件)......

boolean mouseOnScreen;
boolean mouseWithinTopComponent; //is (0 <= mouse.y <= 10)
boolean mouseWithinBottomComponent; //is (screenHeight - 10 <= mouse.y <= screenHeight)
boolean mouseWithinLeftComponent; //is (0 <= mouse.x <= 10)
boolean mouseWithinRightComponent; //is (screenWidth - 10 <= mouse.x <= screenWidth)

if(mouseOnScreen)
{
    if(!mouseWithinBottomComponent)
    {
        //move view up
    }
    if(!mouseWithinTopComponent)
    {
        //move view down
    }
    if(!mouseWithinLeftComponent)
    {
        //move view right
    }
    if(!mouseWithinRightComponent)
    {
        //move view left
    }
}

MouseMotionListener 到底有多少开销?如果只需要沿着游戏窗口的边界进行检测,这种方法或类似方法可能会更有效吗?

注意:这将用于窗口模式以及可能的全屏应用程序。

【问题讨论】:

    标签: java optimization mouse


    【解决方案1】:

    我使用MouseMotionListener 实现了您需要的相同功能。我不确定你为什么认为它会增加开销......如果你添加一个并简单地要求它的每个方法打印到控制台(这很慢)并移动你的鼠标,你会发现它非常活泼从用户的角度来看。

    我的实现由 4 个主要部分组成:滚动窗格、矩形区域、计时器和 MouseMotionListener

    首先,我创建了一个名为AutoScrollPane 的面板,它扩展了JScollPane。即使它是JScrollPane,您也可以隐藏滚动条。这使我可以利用功能在地图上移动视口或类似您所说的 RTS 游戏中的类似功能。

    其次,对于滚动区域,我实际上有 8 个:n、ne、e、se、s、sw、w 和 nw(即“北”、“东北”等),对角线允许对角线滚动。我将它们简单地实现为Rectangles。它们不是在屏幕上或任何东西上绘制的——我只是在我的类中实例化 8 个大小适当且坐标与窗口区域匹配的矩形。我实际上允许我的窗口调整大小,所以我会根据需要调整矩形的大小。

    第三,我有一个可以打开和关闭的计时器。当它打开时,每个“滴答”都会生成一个Runnable。这个Runnable's 的工作是将面板的视口向适当的方向滚动一定距离。每个Runnable 都被交给 Swing 事件队列。

    最后,我有一个MouseMotionListener。它的工作是拦截鼠标进入、退出和移动事件。每次它接收到一个事件时,它都会检查当前鼠标位置以及它是否与其中一个矩形相交。根据哪个矩形,它选择滚动的方向。它跟踪鼠标是否在上一个事件的滚动区域中。基于这些信息,它知道是应该开始滚动、停止滚动,还是让正在发生的事情继续。如果鼠标移出窗格,我希望我的滚动停止,因此使用退出/进入事件。无论如何,要开始滚动,侦听器会保存滚动的方向和距离,并告诉计时器开始。当需要停止滚动时(例如鼠标退出滚动区域时),它会告诉计时器停止。

    选择正确的计时器粒度和滚动距离以实现平滑滚动需要一段时间,但它确实工作得很好。我希望这个大纲能提供一些帮助。

    【讨论】:

    • 非常好的算法描述
    【解决方案2】:

    我认为 Martin Fowler 认为过早优化是软件开发中万恶之源。为什么不试试 MouseMotionListener,只在发现它影响游戏性能时才考虑优化。

    【讨论】:

    • 同意。此外,正是 Knuth 说:“我们应该忘记小的效率,比如大约 97% 的时间:过早的优化是万恶之源。”
    【解决方案3】:

    MouseMotionListener 没有任何问题当您了解开销时,它可能是一个特定的示例

    你可以用任何编程语言做的任何事情都可能做错或做错。

    如果你注意你在听众中所做的一切应该没问题

    【讨论】:

      猜你喜欢
      • 2016-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多