【问题标题】:Andengine: destinguish between OnAreaTouched and OnSceneTouchedAndengine:区分 OnAreaTouched 和 OnSceneTouched
【发布时间】:2012-06-23 17:00:14
【问题描述】:

大家好,

在我使用 AndEngine 开发的游戏中,有很多精灵在跑来跑去。现在每个精灵都有一个 TouchArea 注册到场景中,因为当它被触摸时我会显示一些关于精灵的信息。场景本身有一个 OnSceneTouchListener,我用它来移动相机和缩放。

我的问题是,每次用户移动相机(通过触摸显示屏某处并四处移动手指)时,任何精灵的 OnAreaTouched() 方法,即意外在手指下,被调用,当运动完成时(手指被抬起)。我已经将触发事件限制为event.getAction()==UP(在它被称为touchAreas 的真正混乱之前)但这还不够。如果用户正在缩放或移动相机,则不应激活精灵 touchAreas。

有什么方法可以区分OnAreaTouched-event 和OnSceneTouched-event?哪个先调用,我可以压制另一个吗?

这是我的OnSceneTouched() 方法(简化):

public boolean onSceneTouchEvent(Scene scene, final TouchEvent event) {
    boolean isZooming = event.getMotionEvent().getPointerCount() >= 2;
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        // REMEMBER FIRST TOUCHPOINT, TO KNOW IN WHICH DIRECTION TO MOVE
        this.touchPoint = new Point(event.getMotionEvent().getX(), event.getMotionEvent().getY());  
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        if (isZooming) {
            // DO SOME ZOOM STUFF
        } else {
            // DO SOME MOVEMENT STUFF
        }
        return true;
    }

好的,实际上这不是很有趣 - 但正如您所见,我总是返回 true 以表示已处理触摸事件。 OnAreaTouched() 仍然被调用

这是一个典型的OnAreaTouched()精灵方法:

public boolean onAreaTouched(final TouchEvent touchEvent, float touchAreaLocalX, float touchAreaLocalY) {
    if (touchEvent.getAction() == TouchEvent.ACTION_UP) {
          // DISPLAY INFORMATION ABOUT THE SPRITE
          return true;
    }
    return false;
}

你看,它并没有什么特别之处。所以我希望有人可以在这里帮助我找到一个解决方案,当应该使用OnSceneTouch-event 时,如何抑制OnAreaTouch-event。也许我可以在OnSceneTouched()-Method 中以某种方式捕获event.getAction()==UP

我希望我能很好地解释这个问题,让你理解(对不起,这对我来说并不容易:)。非常感谢任何帮助,感谢您抽出宝贵时间!

问候
克里斯托夫

编辑:

在尝试了 MahdeTo 的建议以某种方式标记事件后,我发现了以下内容:

  • 触发OnSceneTouchEvent()方法的TouchEvent与触发OnAreaTouched()方法的不一样。
  • OnAreaTouched()OnSceneTouchEvent() 晚 20 毫秒被调用
  • 调用OnAreaTouched() 的事件实际上在用户将手指放在显示屏上时开始(然后他移动它并多次调用OnSceneTouchEvent()),然后当他抬起手指时第一个事件停止并获取处理。 (我通过测量时间试了一下)

因此,我想出了测量触摸事件持续时间的解决方案。如果事件超过 200 毫秒,我猜用户不想简单地单击,而是移动或缩放(因为这些操作通常需要更长的时间)。因此,现在OnAreaTouched() 方法仅在有人真正想要单击 并且没有意外滑过该区域时才被调用。

这仍然不是一个好的解决方案,如果有人知道更多关于控制此类事件的信息,我将不胜感激。

谢谢

【问题讨论】:

  • 如何将触摸事件分派给单独的精灵?
  • 我并没有真正派遣他们。 thouchAreas(精灵的)在场景中注册,因此只要触摸事件在这些触摸区域中,就会触发。
  • 尝试在场景触摸的事件上添加标签,并在继续之前在精灵上检查它。如果它类似于 android 的运动事件,则它们具有多路复用标志,例如边缘标志的值为 1、2、4、8,您可以轻松地将 16 设置为您的,而不会破坏任何其他功能,同时如果它相同,则可以区分正在传递的事件实例。
  • 感谢您的提示!正如你告诉我的那样,我将 edgeFlags 设置为 16,但是在 touchArea 方法中记录 edgeFlag 时,它返回 0。所以我猜这是另一个事件。但现在我很困惑。同时触发多少个触摸事件?是不是比我之前处理的运动事件只更新了 10 毫秒?
  • 这是个好问题!您可以通过拥有一个静态集合并将事件推送到那里然后调试它并查看有多少来回答它。也许那时我们就可以知道真正发生了什么。

标签: java android andengine game-engine


【解决方案1】:

我最近使用触摸控件编写了一个相当复杂的应用程序 - 按下屏幕上的按钮、捏缩放、用两根手指旋转和移动对象等等。我最终做的是迭代地改进应用程序并添加规则来控制如何响应不同的触摸事件组合。每当出现问题时,我都会记录 TouchEvent 的顺序并添加规则,以便处理行为不端的操作。

您还可以创建布尔开关来阻止onAreaTouched 执行,只需添加一个条件,例如,如果您想触摸一个对象,检查doNotTouchObject 是真还是假。

我发现另一件有用的东西是触摸模式切换器。我写了几个方法来完全改变用户触摸屏幕时的行为。我相信您可以在旅途中切换它们,因此您应该可以在触摸屏幕时拨打scene.setOnAreaTouchListener(touchListener)

由于取消/注册触摸区域的速度非常快,因此可以在执行某些操作时简单地取消注册某些触摸区域。操作完成后,重新注册。

我使用了以上所有方法的组合,效果很好,但保持代码干净是必不可少的,否则调试或实现新功能会很痛苦。

【讨论】:

  • 你说得对,谢谢。其实这就是我现在做事的方式。由于我找不到合适的解决方案来区分 onArea- 和 onScene-touchEvents,所以我现在设置了标志。所以最后整个 onSceneTouch 方法是一系列 if 条件。它工作得很好,我尽量保持我的代码干净——尽管当用户一次触摸屏幕时触发了两个不同的事件仍然困扰着我。通过类(onSceneTouch - onAreaTouch ....)分层传递这样的事件对我来说更有意义。
  • 也许你正在寻找 mScene.setTouchAreaBindingEnabled(true);这可以解决问题,但我不使用它,所以我无法告诉你是否有任何需要注意的怪癖。
  • @JohnEye ,我知道我说的无关紧要,但你能帮我在每个精灵的 onAreaTouch 方法中实现缩放效果吗?我对 andEngine 非常陌生,并且没有得到那段代码来处理 AreaTouched Listener 上的多点触控。我试图这样做,但这不起作用。 case TouchEvent.ACTION_DOWN: isZooming=pSceneTouchEvent.getMotionEvent().getPointerCount() >= 2;比例因子++;休息;案例 TouchEvent.ACTION_MOVE: if(isZooming) { face2.setScale(scaleFactor) } else { this.setPosition(pSceneTouchEvent.getX() - this.getWidth()/2, pSceneTouchEvent.getY() - this.getHeight()/2 ); }
【解决方案2】:
  1. 也许您可以使用 TouchDetector。 使用 clickDetector 代替处理 TouchUp 事件,则精灵只处理检测到的点击事件; 也将滚动检测器用于场景滚动;

  2. 启用 SceneTouchListenerBinding 和 TouchAreaBinding 还可以帮助您绕过所有意外的进行中事件。

【讨论】:

  • 谢谢,我真的不知道有这么多的可能性!我将更深入地使用它们。所以你说精灵的 ClickDetector 和场景的 Scroll- 和 ZoomDetector?听起来不错,虽然我的第一次测试没有那么成功。我尝试了 PinchZoomDetector 并且在一个场景中它可以工作,但在另一个场景中它只是没有......对于干净的代码来说非常好:) 谢谢,我会告诉你它是怎么回事
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多