Finding the closest object in proxmity to the mouse Coordinates
i've been working on a problem for a while now, which involves targeting the closest movieClip in relation to the x y coords of the mouse, I've attached a nice little acompanying graphic.
Each mc added to the stage has it's own sub-class (HotSpots) which uses Pythag to measure distance from mouse. At this stage i can determine the closest value from my Main class but can't figure out how to reference it back to the movieclip... hope this makes sense. Below are the two Classes.
alt text http://design.camoconnell.com/images/example.jpg
My Main Class which attachs the mcs, and monitors mouse movement and traces closest value
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
public class Main extends MovieClip
{
var pos:Number = 50;
var nodeArray:Array;
public function Main(){
nodeArray = [];
for(var i:int = 0; i < 4; i++)
{
var hotSpot_mc:HotSpots = new HotSpots;
hotSpot_mc.x += pos;
hotSpot_mc.y += pos;
addChild(hotSpot_mc);
nodeArray.push(hotSpot_mc);
// set some pos
pos += 70;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE,updateProxmity)
}
public function updateProxmity(e:MouseEvent):void
{
var tempArray:Array = new Array();
for(var i:int = 0; i < 4; i++)
{
this['tf'开发者_如何学运维+[i]].text = String(nodeArray[i].dist);
tempArray.push(nodeArray[i].dist);
}
tempArray.sort(Array.NUMERIC);
var minValue:int = tempArray[0];
trace(minValue)
}
}
}
My HotSpots Class
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.text.TextField;
public class HotSpots extends MovieClip
{
public var XSide:Number;
public var YSide:Number;
public var dist:Number = 0;
public function HotSpots()
{
addEventListener(Event.ENTER_FRAME, textUp);
}
public function textUp(event:Event):void
{
XSide = this.x - MovieClip(root).mouseX;
YSide = this.y - MovieClip(root).mouseY;
dist = Math.round((Math.sqrt(XSide*XSide + YSide*YSide)));
}
}
}
thanks in advance
Seems to be straight forward ...
Add a method to into the HotSpots
so you can externally set its state :
public function set isClosest(value:Boolean):void
{
// do something here, example :
alpha = (value) ? 1 : .5;
}
Each time you've updated the distances you can now use the newly created method to make the HotSpots 'aware' of their respective position :
for(var i:int = 0; i < 4; i++)
{
// sets the first hotspot to isClosest = true and the others to false ...
(nodeArray[i] as HotSpots).isClosest = (i == 0);
}
EDIT : Following your second answer, ...
Quickly to find the closest without using Array.sortOn
you can proceed like following. But now I think the whole code is a bit of the wrong way around (why would you have to calculate the distance from within the object, etc.).
// For iteration only
var hotSpot:HotSpots;
// Keeps track of the so far closest hotSpot
var closestHotSpot:HotSpots;
// Stores the so far closest distance (to avoid recalculating each time)
var closestDistance:Number;
// Finds out the closest
for each(hotSpot in nodeArray)
{
if(closestHotSpot == null || nodeArray[i].dist < closestDistance)
{
closestHotSpot = hotSpot;
closestDistance = hotSpot.dist;
}
}
// Applies the right state to each of the hotSpots
for each(hotSpot in nodeArray)
{
hotSpot.isClosest = (hotSpot == closestHotSpot);
}
Ok, so i've got it working....
But i'm quite tired and believe i've most likely well over-engineered the solution. I took your advice, thanks Theo, and added a setter method to the Hotspot Class and run a for loop that 'sets the first hotspot to isClosest = true and the others to false..'
The problem i was having was that the second Array (which i've now named 'sortArray') only held each 'HotSpots' distance from the mouse, so once i sorted the array in acsending order (from shortest dist to longest dist)i only had the distance string and nothing to reference (as in a index number) against the nodeArray. To counter this i pushed an object into the sortArray that holds the distance parameter and an index parameter. then using the sortOn() method i could sort the distance parameter then use the corrosponding index parameter to locate the appropiate mc in nodeArray.
Seems really long winded...
Main.as
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
public class Main extends MovieClip
{
var pos:Number = 50;
var nodeArray:Array;
public function Main(){
nodeArray = [];
for(var i:int = 0; i < 4; i++)
{
var hotSpot_mc:HotSpots = new HotSpots;
hotSpot_mc.x += pos;
hotSpot_mc.y += pos;
addChild(hotSpot_mc);
nodeArray.push(hotSpot_mc);
// set some pos
pos += 70;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE,updateProxmity)
}
public function updateProxmity(e:MouseEvent):void
{
var sortArray:Array = [];
for(var i:int = 0; i < 4; i++)
{
this['tf'+[i]].text = String(nodeArray[i].dist);
var ob:Object = {}
ob.dist = String(nodeArray[i].dist);
ob.arrayPos = i;
sortArray.push(ob);
}
sortArray.sortOn("dist",Array.NUMERIC);
var minValue:int = sortArray[0];
for(var j:int = 0; j < 4; j++){
(nodeArray[j] as HotSpots).isClosest = (j == sortArray[0].arrayPos);
}
}
}
}
oh, and here's the amended HotSpots Class
package {
import flash.display.MovieClip;
public class HotSpots extends MovieClip
{
public var XSide:Number;
public var YSide:Number;
public var dist:Number = 0;
public function HotSpots()
{
}
public function textUp():void
{
XSide = this.x - MovieClip(root).mouseX;
YSide = this.y - MovieClip(root).mouseY;
dist = Math.round((Math.sqrt(XSide*XSide + YSide*YSide)));
}
public function set isClosest(value:Boolean):void
{
var stopPos = (value) ? 2 : 1;
this.gotoAndStop(stopPos);
}
}
}
精彩评论