BIT-101 [2003-2017]

hitTest in loaded movies


Boy do I feel foolish. Not only can I not believe that I never knew this, but I can’t believe I never had a problem with this. I only now just discovered that the x, y point fed to hitTest must be in terms of the main Stage, or global coordinates. How did this escape me for so many years and how did this only cause a problem now???

This revelation came about as I am redesigning my site. I’ve always kept the main content window in the upper left corner, due to the fact that I always loaded the experiments into a level, not a movie clip. I had to do this because many of my experiments refer to _root, and some of them would be messed up if loaded into a clip. So I kept loading into a level and kept the level at 0, 0.

Then, along came _lockroot. Now I can load my experiments into a clip, which can be anywhere on the stage. Assigning _lockroot=true to the clip keeps the clip’s _root contained to the clip. Great!

But once I did that, I found that a whole lot of my experiments still weren’t working right. I tracked it down to those which used hitTest. None of the tests were working right. So, after trying everything else, I turned to ASDG. Lo and behold, the hitTest point must be in terms of Stage (global) coords. Because my experiments sometimes just test _xmouse or _ymouse, or test the position of a clip against another clip, and the window containing the experiment’s local coords were now different than the global coords, it was always off. Because my experiment window had always been at 0, 0 before, I never ran into this problem. Wow.

Now, how to fix it? I didn’t really want to search through almost 600 files looking for hitTests. And even if I did, just using _root._xmouse wouldn’t help, because of _lockroot – _root._xmouse would still not be the global stage _xmouse. And in the case of testing a clip against the x, y coords of another clip. There’d be no easy way to change it. I’d have to go in and write a localToGlobal function in every single experiment that had a hitTest in it.

Finally, I went to bed, where I do my best thinking. As usual, lying there trying to go to sleep, the solution came to me. Overwrite hitTest to include a localToGlobal conversion. here’s what I came up with:

MovieClip.prototype.oldHitTest = MovieClip.prototype.hitTest;
MovieClip.prototype.hitTest = function(x, y, sf){
	var obj = {x:x, y:y};
	this._parent.localToGlobal(obj);
	return this.oldHitTest(obj.x, obj.y, sf);
}

This saves the original hitTest function as “oldHitTest” in MovieClip.prototype. Then creates a new version. This takes the testing point and assigns it to an object. Then it runs localToGlobal on the point. “this._parent” refers to the timeline that the calling object is on. If that timeline’s coordinates are different than global, the object will now contain the converted global coordinates. We then use these coordinates to call “oldHitTest”, which will return true or false, and pass that back to the caller.

Seems to work, and saved me many hours.

« Previous Post
Next Post »