我是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