0

私は ActionScript 3.0 を初めて使用します。http://www.senocular.com/flash/tutorials/as3withmxmlc/でチュートリアルを試しました。デモ プログラムは、ボールをアニメーション化し、ドラッグできるようにします。

書かれているプログラムに問題がありました。マウスをステージの外にドラッグしてマウス ボタンを離すと、ボールは MOUSE_UP イベントを取得しません。したがって、コードは決して stopDrag() を呼び出しません。私は提案のためにstackoverflowを検索しました.1つの提案は、ステージとボールで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;
    }
}           

私はこのコードがあまり好きではありません。問題は、すべてのケースを 1 か所で検出できないことに帰着します。私はこのようなものを書きたいと思います:

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

このロジックにより、より確実でシンプルなケース処理と明確なロジックを書くことができます。現状では、このようにコードを編成する方法から生じる複雑な動作が多数あります。

イベント リスニング モデルでは、これが可能ではないようです。イベントへの対応は個別に行われる必要がありますか? 「キューに入っている」イベントを検出する方法はありますか?

別の方法として、startDrag() を使用しないようにすることもできます。つまり、ボール スプライトをドラッグ可能にすることを避け、ステージだけが MOUSE_UP をリッスンし、すべてのドラッグ ロジックを自分で処理することもできます。これにより、ユーザーがステージの外にドラッグしたときにボールを配置する場所などの質問をより適切に処理できるようになります。全体的にはそのほうがいいのかな。

4

2 に答える 2

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)
    }
于 2013-07-11T19:52:13.703 に答える