2013-07-11 82 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樂趣。沒有更多的醜陋需要。

相關問題