SyntaxScrewer's Blog

October 11, 2010

event.stageX vs mouseX – credits to mrmg from #irc – Horizontal Drag n Scroll Carousel related issue

Filed under: ActionScript 3.0,Flash — geekymaira @ 3:51 pm

[WARNING: The title of this post might not seem relevant, unless you read the whole thing]

Hey,

I’ve been working on a game where I needed a scrolling horizontal carousel (if you may).
I made a simple class to handle the scrolling based on the mouseX. It worked , but was
buggy. I tried but couldn’t figure out what was wrong. Hence, IRC 😀

Anyway, there were 2 issues. I’ll explain them with code and examples.

ISSUE 1: It seems like the solution to this issue, didn’t change much visually, but I like this way better.
Feels more logical. So I had my class setup like below.

package views 
{
	import utils.Constants;
	import com.greensock.TweenLite;
	import flash.events.MouseEvent;
	import com.greensock.easing.Quart;

	import flash.display.MovieClip;

	/**
	 * @author Sameer Maira
	 */
	public class CarouselBaseClass extends MovieClip 
	{
		private var scrolling : Boolean;
		private var lastX : Number;
		private var _carousel : MovieClip;
		private var _parent : MovieClip;
		private var carouselTween : TweenLite;
		private var newX : Number = 0;
		private var _spacing : Number;

		public function CarouselBaseClass()
		{
		}

		public function setupScrolling(target : MovieClip,spacing:Number)
		{
			_carousel = target;
			_spacing = spacing;
			
			_carousel.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			Constants.MAIN_STAGE.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			_carousel.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}

		private function onMouseMove(event : MouseEvent) : void
		{
			if (scrolling)
			{		
				if (mouseX < lastX)
				{		
					if (newX > -1287)
					{
						newX = _carousel.x - _spacing;
					}
				}
				if (mouseX > lastX)
				{
					if (newX < 0)
					{
						newX = _carousel.x + _spacing;
					}
				}
				if (mouseX != lastX)
				{	
					carouselTween = TweenLite.to(_carousel, 1, {x:newX, ease:Quart.easeOut});
				}
			}
		}

		

		private function onMouseUp(event : MouseEvent) : void
		{
			scrolling = false;	
		}

		private function onMouseDown(event : MouseEvent) : void
		{
			lastX = mouseX;
			scrolling = true;
		}
	}
}

Now, the issue that was pointed out was with the way I had my event listeners setup for the MOUSE_UP, MOUSE_MOVE & MOUSE_DOWN events. Plus I was using the “scrolling”
boolean which wasn’t really needed when I fixed the event listeners. The solution(better implementation) was to :

1) add the MOUSE_UP & MOUSE_MOVE event listeners to the stage.
2) add the MOUSE_MOVE & MOUSE_UP event listeners when the MOUSE_DOWN was triggered.
3) remove the MOUSE_UP & MOUSE_MOVE when the MOUSE_UP was triggered.

The code then looked something like what’s given below :
PS: I realized a few other silly things I had done, which were corrected & commented in the code.

package views 
{
	import utils.Constants;

	import com.greensock.TweenLite;
	import com.greensock.easing.Quart;

	import flash.display.MovieClip;
	import flash.events.MouseEvent;

	/**
	 * @author Sameer Maira
	 */
	public class CarouselBaseClass extends MovieClip 
	{
		private var scrolling : Boolean;
		private var lastX : Number;
		private var _carousel : MovieClip;
		private var _parent : MovieClip;
		private var carouselTween : TweenLite;
		private var newX : Number = 0;
		private var _spacing : Number;

		public function CarouselBaseClass()
		{
		}

		public function setupScrolling(target : MovieClip,spacing : Number)
		{
			_carousel = target;
			_spacing = spacing;	
			_carousel.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		}

		private function onMouseMove(event : MouseEvent) : void
		{
			//Dont want it to scroll if the mousePos hasn't changed.
			//On the other hand. Why would this event handler be triggered if the mouse position hasn't changed
			//you idiot. Sheesh!
			
			//TODO: Get a brain.
			if (mouseX != lastX)
			{
				if (mouseX < lastX)
				{
					//TODO: Cannot hard code the bound limits - different for different derived class objects.
					//Pass them as params.
					if (newX > -1287)
					{
						newX = _carousel.x - _spacing;
					}
				}
				if (mouseX > lastX)
				{
					if (newX < 0)
					{
						newX = _carousel.x + _spacing;
					}
				}
				TweenLite.killTweensOf(_carousel);	
				carouselTween = TweenLite.to(_carousel, 1, {x:newX, ease:Quart.easeOut});
			}
		}

		private function onMouseUp(event : MouseEvent) : void
		{
			//scrolling = false;	
			Constants.MAIN_STAGE.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			Constants.MAIN_STAGE.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
		}

		private function onMouseDown(event : MouseEvent) : void
		{
			lastX = mouseX;
			//scrolling = true;
			Constants.MAIN_STAGE.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			Constants.MAIN_STAGE.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
		}

	}
}

ISSUE 2: So, the reason for this post is this issue. Basically my scrolling was buggy. You can see why if you look
at the example below.

[EXAMPLE]

The scrolling seems a bit jittery doesn’t it ? Yes it does. Try scrolling small amounts. It’s still jittery.
The various probable causes that we thought of (just to mention) were.

– The Children are catching the mouseEvents (The hikers & the numbers) : Verified to make sure mouseChildren = false;
– The Tweens were overlapping. ie. Before the 1st tween could complete, another tween would begin due to the dragging. : Killed all tweens for the object before starting a new tween.

None of the above were the issue.

Finally mrmg, suggested that I replace “mouseX” and use “event.stageX” instead. Well guess what!!! That worked.
I’m not sure why but from what I got to know from mrmg (by the way, that’s a person on IRC), was that it might be due to 2 issues.

– Local/Global coordinate problem
– The mouseX value might be getting cached on the last frame of the event handler, whereas event.stageX was not.

I’m not sure if I still understand, why it really solved the issue. I’m glad it did or else I’d be stuck for days.
If you know the reason, please comment. I really want to know.

Here’s how it looks after the correction.

[EXAMPLE FIXED]

Great little nugget of information.
All thanks to mrmg.

-SyntaxScrewer

Advertisements

2 Comments »

  1. This is weird. I had the exact reverse problem. When I had a complex movie clip on the stage, that was scaled larger, the event.stageX variable was only incrementing in “jumps”, when moving the mouse small amounts, the value wouldn’t change, then all of a sudden jump up by 10-20 pixels. When I changed this to use stage.mouseX it fixed the problem and everything went smoothly.

    Comment by Paul — April 17, 2012 @ 8:56 am | Reply

  2. I had a similar “jittery movement” problem with event.stageX! I lost many days, debugging everything until after really serious analysis I found that it was a problem of flash, not mine. Switching to stage.mouseX did the trick. It was the most problematic bug in my life 😀

    Comment by Markus — September 3, 2012 @ 10:26 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: