detecting changes to the location of sprite
What is a good strategy for detecting when the position (x, y) of a sprite, relative to the stage, has changed? In other words, how can I detect changes to a sprite's global position?
This becomes difficult when the sprite is the child of other DisplayObjectConta开发者_运维问答iner objects.
Is it a UIComponent
or just a Sprite
? I'm not sure how to do it if it's just a Sprite
, but if it's a UIComponent
it's doable, but could get messy.
You'd have to listen to the component's move event. When you get that event you can get its position and convert that to global coordinates using the localToGlobal() method.
Unfortunately I think you'd have to also listen to move
events for all of its parent components as well, as I don't think a component will raise the move
event if its parent moves.
There might be a cleaner way to do this, but if not this should work.
You could create a sub-class of Sprite
and override the public function set x(value:Number):void
and public function set y(value:Number):void
simple exemple:
public class Exemple extends Sprite{
override public function set x(value:Number):void{
super.x=value;
dispatchEvent(new Event("move"));
}
override public function set y(value:Number):void{
super.y=value;
dispatchEvent(new Event("move"));
}
}
Also, have a look at the Event.RENDER
event...
If you really want this, and you want it accurate, make an onEnterFrame and nest something like this inside it:
var vals:Object = new Object;
function checkPositionChanged(obj:DisplayObject):Boolean
{
var bool:Boolean = false;
var pt:Point = new Point(obj.x,obj.y);
pt = pt.localToGlobal(obj);
if( vals.x != pt.x || vals.y != pt.y ){
bool = true;
}
vals.x = pt.x;
vals.y = pt.y;
return bool;
}
The only way I can think is having a function called on the EnterFrame
event and check the lacalToGloabal
coordinates tested against a stored property. The problem is that this can become rather resource intensive if you have a lot of sprites. You can alleviate the problem somehow enabling and disabling the event handler based on external conditions. Otherwise I would really consider talking the problem the other way around and concentrate on the circumstances that may move the sprites, that is, the triggers and not the effects, if this is possible.
Just had the same problem.
I have written a manager that listens to all ancestors move events, and updates listeners when adding-to/removing-from stage. It dispatches a GlobalMoveEvent with the stage x/y coordinates of the component in question.
It currently works for UIComponents only, but is designed to be extenable to Sprite etc.
Let me know if you are interested.
Another solution would be to create a "thread" using Timer to check the position using localToGlobal()
every, say, 100ms. There would be delay between when the move happens and you get the event, but that way you wouldn't have to look at the entire display list to tell if the sprite or any of its parents changed. You'd just check the global position of the sprite, and if it's changed you call something.
You could even create a helper class that could check multiple sprites. Then you'd just register sprites with it, and each time it runs it would check all of them and raise a move event for each sprite it detects moved. Probably wouldn't be too hard to create it.
Again, this wouldn't be perfect, as you wouldn't get the events immediately after the move, but if you don't need to know right away it might be good enough.
You could accomplish this based on a modification of OXMO456's suggestion. As you are concerned about the notifications based on it's position in the stage, and not neccessarily it's parent, you can simply cache and compare the 'global' coordinates, and fire when that changes.
useful methods to know:
localToGlobal
globalToLocal
public class Example extends Sprite{
private var stagePoint:Point = new Point(0,0);
override public function set x(value:Number):void{
super.x=value;
if(stage != null){
var globalPoint:Point = this.parent.localToGlobal(new Point(x,y));
if(globalPoint.x != stagePoint.x){
stagePoint = globalPoint;
dispatchEvent(new Event("move"));
}
}
}
override public function set y(value:Number):void{
super.y=value;
if(stage != null){
var globalPoint:Point = this.parent.localToGlobal(new Point(x,y));
if(globalPoint.y != stagePoint.y){
stagePoint = globalPoint;
dispatchEvent(new Event("move"));
}
}
}
}
EDIT: Oh wait, I think I mis-interpreted what you were asking, doh! I'll leave this up in case it's useful in some other way.
Can you give some more detail about the problem you're trying to solve by doing this? That might help us zero in on a solution that will work without deal-breaking overhead (like a ton of registered event listeners or some such)
精彩评论