如何在 actionscript 中将 Sprite 平滑地拖到屏幕上

How drag a Sprite smoothly on-screen in actionscript

首先我的问题和这个基本一样:

How to drag an image to move it smoothly on screen, with ActionScript?

我希望我拖动的 Sprites 能够顺畅地跟上屏幕上的鼠标,不会落后。

而且我注意到,在过去的旧 ActionScript 3 Cookbook 中,他们使用与上面 link 中使用的类似的 DraggableSprite 解决方案。即,使用 stage 实例监听 MouseMove 事件,然后读取 event.stageX 和 stageY 属性。

我做到了。

但是我的 Sprite 仍然没有被鼠标光标锁定。它落后了。我觉得我一定是错过了什么。但是,如果上面发布的解决方案(即侦听舞台的 MouseMove 和使用事件。stageX/Y)仍然是最新的并且我描述的问题不应该发生,也请告诉我。尽管它不应该起作用,但我已经尝试过 event.updateAfterEvent() 并且它似乎也没有任何积极作用。

如有任何帮助或建议,我们将不胜感激。

这是我如何编写处理程序的简单示例。如果粘贴到新项目中,它应该可以按原样工作。

我还应该补充一点,我正在使用 Adob​​e AIR 将其编译为桌面应用程序。 运行 时间会是一个因素吗???

package {
  import flash.display.Sprite;
  import flash.events.MouseEvent;

  [SWF(width="1280", height="720", frameRate="30")]
  public class test_drag extends Sprite {

    private var testDragSprite:TestDragSprite;

    public function test_drag() {
      super();

      graphics.clear();
      graphics.beginFill(0x0000FF);
      graphics.drawRect(0, 0, 1280, 720);
      graphics.endFill();

      testDragSprite = new TestDragSprite();
      addChild(testDragSprite);

      testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
      testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);
    }

    private function testDragSprite_mouseHandler(e:MouseEvent):void {
      switch (e.type) {
        case MouseEvent.MOUSE_DOWN: {
          stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
          break;
        }
        case MouseEvent.MOUSE_UP: {
          stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
          break;
        }
      }
    }

    private function mouseMoveHandler(e:MouseEvent):void {
      //-20 to keep the sprite centered on the mouse
      testDragSprite.x = e.stageX - 20;
      testDragSprite.y = e.stageY - 20;
      //e.updateAfterEvent(); //strange effect, but doesn't solve the problem.
    }
  }
}
import flash.display.Sprite;
internal class TestDragSprite extends Sprite {
  public function TestDragSprite() {
    super();
    graphics.lineStyle(1, 0xDDDDDD);
    graphics.beginFill(0xFF0000);
    graphics.drawRoundRect(0, 0, 40, 40, 12);
    graphics.endFill();
  }      
}

试试成员函数startDrag.

总会有一点延迟,但是:

前两个建议会对您的 code/performance 产生最明显的改变。

  • 启用硬件图形加速;编辑您的 AIR 应用程序 描述符文件 (xml) 并将渲染模式设置为直接(或 GPU)。咨询 有关详细信息,请访问 Adob​​e Air 帮助。

    <!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto -->
    <renderMode>direct</renderMode>
    
  • 使用 startDrag 和 endDrag 绕过 mouseMoveHandler 中的手动分配。

替换:

testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);

有:

testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, mouseUp);

添加新的处理程序:

private function mouseDown(e:MouseEvent):void {
    testDragSprite.startDrag();
}
private function mouseUp(e:MouseEvent):void {
    testDragSprite.stopDrag();
}
  • 提高你的帧率,但注意你的 CPU 用法,因为你的 application/game 变得越来越复杂,因为你可能需要降低它以使你的游戏逻辑有足够的时间来完成帧之间(否则你最终会得到所谓的长帧,你可以使用免费的 Adob​​e Scout 分析工具来观察这些和许多其他东西)。

  • 将帧率 HUD 添加到您的显示器,以便您可以监控实际帧率何时低于请求的帧率(这用于调试)

  • 如果您的游戏是基于 2d 的,请考虑使用开源 Starling framework,因为与 Flash 的标准显示列表对象相比,所有内容均由 GPU 直接渲染。

Feathers UI 库包含一个拖放模块。上面的答案都使用了不支持移动设备的 'old' 显示列表。如果您希望您的代码跨平台工作,您需要一个 GPU 框架(最受欢迎的是 Feathers 所基于的 Starling,以及大多数 Adob​​e AIR 游戏和应用程序)。