【问题标题】:ActionScript 3, handling MOUSE_UP outside stageActionScript 3,在舞台外处理 MOUSE_UP
【发布时间】:2013-07-11 19:50:36
【问题描述】:

我是 ActionScript 3.0 的新手。我在http://www.senocular.com/flash/tutorials/as3withmxmlc/ 尝试了一个教程。演示程序对球进行动画处理并允许对其进行拖动。

编写的程序有问题。当您将鼠标拖到舞台外并释放鼠标按钮时,小球不会获得 MOUSE_UP 事件。因此,代码永远不会调用 stopDrag()。我在stackoverflow上搜索了一些建议,其中一个建议是用舞台和球听MOUSE_UP,并添加一些处理它的逻辑。

我添加了一些代码来执行此操作。我还按照编写的程序重构了程序,因为它非常杂乱无章。这是我现在拥有的:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    public class BallToss extends Sprite {
        private var ball:TossableBall;
        // mouse position at last call to trackMouseMvt()
        private var lastMousePos:Point = new Point();
        // delta mouse movement from frame L-1 to frame L, where L is last frame
        private var lastDeltaMouse:Point = new Point();

        public function BallToss() {
            var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth, 
                                                      stage.stageHeight);
            ball = new TossableBall(50, stageBounds);
            ball.x = stageBounds.width/2;
            ball.y = stageBounds.height/2;
            addChild(ball);
            ball.addEventListener(MouseEvent.MOUSE_DOWN, grabBall);
            // however I order the next two calls to addEventListener(), it seems 
            // that the ball's MOUSE_UP gets handled before the stage's MOUSE_UP
            stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
            ball.addEventListener(MouseEvent.MOUSE_UP, releaseBall);
            // initialize 'lastMousePos' and set up 'trackMouseMvt' to be called on
            // every frame
            lastMousePos = new Point(mouseX, mouseY);
            ball.addEventListener(Event.ENTER_FRAME, trackMouseMvt);
        }

        private function grabBall(evt:MouseEvent):void {
            trace("in grabBall");
            // set ball 'glideVector' to (0,0) so it will stop moving
            ball.setGlideVector(new Point(0,0));
            ball.startDrag();
        }

        private function releaseBall(evt:MouseEvent):void {
            trace("in releaseBall");
            ball.stopDrag();
            // set up the ball to glide at the rate of 'lastDeltaMouse'
            ball.setGlideVector(lastDeltaMouse);
        }

        private function trackMouseMvt(evt:Event):void {
            var currMouse:Point = new Point(mouseX, mouseY);
            lastDeltaMouse = currMouse.subtract(lastMousePos);
            lastMousePos = currMouse;
        }

        private function handleStageMouseUp(evt:Event):void {
            trace("in handleStageMouseUp"); 
            ball.stopDrag();
            var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth, 
                                                      stage.stageHeight);
            if (ball.x > stageBounds.right - 0.5)
                ball.x = stageBounds.right - 0.5;
            else if (ball.x < 0) 
                ball.x = 0;
            if (ball.y > stageBounds.bottom - 0.5)
                ball.y = stageBounds.bottom - 0.5;
            else if (ball.y < 0)
                ball.y = 0;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;

class TossableBall extends Sprite {

    private var stageBounds:Rectangle;
    private var glideVector:Point = new Point();
    private var friction:Number = .95;

    public function TossableBall(size:Number, stageBoundsIn:Rectangle) {
        stageBounds = stageBoundsIn;
        graphics.lineStyle(1);
        graphics.beginFill(0xFF8000);
        graphics.drawCircle(0, 0, size/2);
        addEventListener(Event.ENTER_FRAME, glide);
    }

    public function setGlideVector(glideVectorIn:Point):void {
        glideVector = glideVectorIn;
    }

    private function glide(evt:Event):void {
        x += glideVector.x;
        y += glideVector.y;
        var shapeBounds:Rectangle = getBounds(parent);
        if (shapeBounds.left < stageBounds.left) {
            glideVector.x = Math.abs(glideVector.x);
        } else if (shapeBounds.right > stageBounds.right) {
            glideVector.x = -Math.abs(glideVector.x);
        }
        if (shapeBounds.top < stageBounds.top) {
            glideVector.y = Math.abs(glideVector.y);
        } else if (shapeBounds.bottom > stageBounds.bottom) {
            glideVector.y = -Math.abs(glideVector.y);
        }
        glideVector.x *= friction;
        glideVector.y *= friction;
    }
}           

我不太喜欢这段代码。问题归结为无法在一个地方检测到所有病例。我想写这样的东西:

if (..ball and stage both got MOUSE_UP..) {
    ..handle it..;
else if (..only stage got MOUSE_UP..) {
    ..handle it..;
}

这个逻辑可以让我写出更万无一失、更简单的案例处理和更清晰的逻辑。就目前而言,这种组织代码的方式会产生很多复杂的行为。

事件监听模型似乎无法做到这一点。对事件的反应必须单独发生,还是必须发生?有没有办法检测“队列中”的事件?

或者,我可以避免使用 startDrag(),即避免使球 Sprite 可拖动,并且只让舞台监听 MOUSE_UP,然后自己处理所有拖动逻辑。这也可以让我更好地处理当用户拖出舞台时我希望球放置在哪里等问题。我想知道这是否总体上更好。

【问题讨论】:

  • 不要发布您的所有代码,只发布您问题范围的相关块。
  • @composerMike 你的问题解决了吗?
  • 是的。我根据其他地方发布的信息解决了它。

标签: actionscript-3


【解决方案1】:

要跟踪被拖动的对象,这对我很有用:


ball.addEventListener(MouseEvent.MOUSE_DOWN, onBallMouseDown)


    var _stage:Stage;

    private function onBallMouseDown(e:MouseEvent):void 
    {
        _stage = stage;
        stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
        stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
        ball.startDrag();
    }

    private function onStageMouseMove(e:MouseEvent):void 
    {
        // track ball coordinates
    }

    private function onStageMouseUp(e:MouseEvent):void 
    {
        ball.stopDrag();
        _stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
        _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
    }

【讨论】:

    【解决方案2】:

    那又如何,经过多年的 Flash 编程,我现在才发现MouseEvent.RELEASE_OUTSIDE 的乐趣。不再需要丑陋的黑客攻击。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 2011-08-03
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      相关资源
      最近更新 更多