2013-07-11 52 views
0

我是ActionScript 3.0的新手。我在http://www.senocular.com/flash/tutorials/as3withmxmlc/尝试了一个教程。演示程序使球动画并允许拖动它。ActionScript 3,在舞台外处理MOUSE_UP

该程序存在问题,如书面。将鼠标拖出舞台并释放鼠标按钮时,球不会获得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,然后自己处理所有拖动逻辑。这也让我能够更好地处理问题,比如当用户拖出舞台时,我希望球能够定位在哪里。我想知道这是否更好。

+0

不要发布您的所有代码,只是您问题范围的相关块。 – ILikeTacos

+0

@composerMike你解决了你的问题吗? – ZuzEL

+0

是的。我根据别处发布的信息解决了这个问题。 – composerMike

回答

0

要跟踪被拖动对象这部作品对我好:


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) 
    } 
0

怎么样,经过多年的Flash编程的只有现在我已发现的MouseEvent.RELEASE_OUTSIDE乐趣。没有更多的丑陋需要。

相关问题