我是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,然後自己處理所有拖動邏輯。這也讓我能夠更好地處理問題,比如當用戶拖出舞臺時,我希望球能夠定位在哪裏。我想知道這是否更好。
不要發佈您的所有代碼,只是您問題範圍的相關塊。 – ILikeTacos
@composerMike你解決了你的問題嗎? – ZuzEL
是的。我根據別處發佈的信息解決了這個問題。 – composerMike