Object to Object Vicinity
My last post on vicinity was a bit of a hoax. It was based off mouse position and not true reference of one object to another. Rest assured, this post is legit!
I think the level of difficulty is going to rise exponentially from here on in until I reach my goal, so theres gonna be a bunch of code that may or may not make sense. But I’ll try to break it down for you because I’ve found some of this stuff quite helpful.
I broke down the tasks as such.
1) All objects listen for a dispatched event from the currently selected object.
2) Compare the currently selected object’s x and y position with all the other objects individual x and y.
3) Specify a radius around the currently selected object.
4) if all objects fall withing that radius they are in close vicinity and change their alpha value.
Sounds easy enough?
I had a problem getting the objects to listen for external events. So if one object sent an event, the other objects couldn’t pick that up. I found a solution that harks back to AS2 days where you create one static Event Dispatcher class and make all objects listen to that one class. So if I roll over one object, that object then calls the static Event Dispatcher, all other objects are listening for this event and when it is called they all react at once.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | /** * A central event broadcaster * * @author Zack Jordan * { P I X E L W E L D E R S . C O M } */ package { import flash.events.Event; import flash.events.EventDispatcher; public class Broadcaster { private static var eventDispatcher : EventDispatcher; public static var cX:*; public static var cY:*; /** * Broadcasts an event to all listeners * To listen to any and all events, use Broadcaster.addEventListener() * * @param event The Event to broadcast * @return nothing */ public static function broadcast( event:Event, info1:* = null, info2:* = null ): void { cX = info1; cY = info2; dispatchEvent( event ); } // === S T A T I C E V E N T D I S P A T C H E R === public static function addEventListener( type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=true ):void { if ( !eventDispatcher ) eventDispatcher = new EventDispatcher(); eventDispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference ); } public static function removeEventListener( type:String, listener:Function, useCapture:Boolean=false ):void { if ( eventDispatcher ) eventDispatcher.removeEventListener( type, listener, useCapture ); } public static function dispatchEvent( p_event:Event):void { if ( eventDispatcher ) eventDispatcher.dispatchEvent( p_event ); } } } |
All credit for this goes to PixelWelders, and the original post can be found here. I just added a couple public variables so I could pass the currently selected object’s x and y to all the other objects.
Now we can get into the nuts and bolts of making it work.
To use this broadcaster just call the class and broadcaster() method. Pass the Event and x and y position like this. Here is my code and I will break through it piece by piece.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | package { import flash.display.*; import flash.events.* import Broadcaster public class Vicinity extends MovieClip { public static const OVER:String = "Over" public static const OUT:String = "Out" public function Vicinity() { this.addEventListener(MouseEvent.MOUSE_OVER, mOver) this.addEventListener(MouseEvent.MOUSE_OUT, mOut) Broadcaster.addEventListener(Vicinity.OVER, over) Broadcaster.addEventListener(Vicinity.OUT, out) } private function over(e:Event):void { var distanceX = Math.abs(this.x - Broadcaster.cX); var distanceY = Math.abs(this.y - Broadcaster.cY); xText.text = String(distanceX) yText.text = String(distanceY) if(distanceX < 150 && distanceY < 150) { bg.alpha = 0.2 } else { bg.alpha = 1 } } private function out(e:Event):void { bg.alpha = 1 } private function mOver(e:MouseEvent):void { Broadcaster.removeEventListener(Vicinity.OVER, over) xText.text = "0" yText.text = "0" Broadcaster.broadcast(new Event(Vicinity.OVER), this.x, this.y) } private function mOut(e:MouseEvent):void { Broadcaster.addEventListener(Vicinity.OVER, over) Broadcaster.broadcast(new Event(Vicinity.OUT)) } } } |
15 16 17 18 19 | this.addEventListener(MouseEvent.MOUSE_OVER, mOver) this.addEventListener(MouseEvent.MOUSE_OUT, mOut) Broadcaster.addEventListener(Vicinity.OVER, over) Broadcaster.addEventListener(Vicinity.OUT, out) |
Sets up the event listeners. Listens if the object is rolled over, and sets up the Broadcaster Listener.
42 43 44 45 46 47 48 49 50 51 52 53 | private function mOver(e:MouseEvent):void { Broadcaster.removeEventListener(Vicinity.OVER, over) xText.text = "0" yText.text = "0" Broadcaster.broadcast(new Event(Vicinity.OVER), this.x, this.y) } private function mOut(e:MouseEvent):void { Broadcaster.addEventListener(Vicinity.OVER, over) Broadcaster.broadcast(new Event(Vicinity.OUT)) } |
After the current object is rolled over it dispatches that static Event Dispatcher and passes it’s x and y values as well
Broadcaster.broadcast(new Event(Vicinity.OVER), this.x, this.y)
If you were wondering about the removeEventListener being called first, that makes it so the currently selected object isn’t affected. We only want the objects in vicinity to be affected.
So now we’ve got the static Event Dispatcher working. Remember we previously set up the static Event Dispatcher to listen for events? This is where we handle them.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | private function over(e:Event):void { var distanceX = Math.abs(this.x - Broadcaster.cX); var distanceY = Math.abs(this.y - Broadcaster.cY); xText.text = String(distanceX) yText.text = String(distanceY) if(distanceX < 150 && distanceY < 150) { bg.alpha = 0.2 } else { bg.alpha = 1 } } private function out(e:Event):void { bg.alpha = 1 } |
Here we pick up the previously sent x and y that was sent to the static Event Dispatcher from the selected object.
var distanceX = Math.abs(this.x - Broadcaster.cX); var distanceY = Math.abs(this.y - Broadcaster.cY)
What I did in these two lines is compare the object’s x and y with the selected object’s x and y. And what we result in is the distance the object is away from the selected object.
if(distanceX < 150 && distanceY < 150) { bg.alpha = 0.2 } else { bg.alpha = 1 }
Here I just did here was an if statement that checks if the object is within vicinity of the selected object. If it is, change alpha, if it isn’t make sure it has a solid alpha. In essence the value 150 is the radius of a circle, and any object the falls inside that radius has an effect put upon it, the others are left alone.
By building it this way I can get proper object to object interactions. It also should cut down on processing power because only code is carried out on rollOver events, not continually running EnterFrame events like in the previous post.
Oh yeah, and here is the result!
