Interactive Designer and Developer
Collider Exhibit Series

Add, Move and Remove MovieClip from Library via Touch Point

thumbI received a request on my Blob Lines Tutorial from Simplex

I just want to put a Movieclip under each blob, move each Movieclip when blobs move AND remove the Movieclip when blob is away

Simple, right? Well not at first for me. This is something I've been trying to work out for a while. What is a clean solution to pull a MovieClip from the library dynamically onto the stage...keep tracking that MovieClip with the one specific blob...then remove it when that blob is removed. And I must say, I was scratching my head on this one for a while. I would get to the point of removing the MC, and it would all fall apart from the way I thought I should work.

Now before we start, time for a little file preparation.

  1. Make your new Flash File, 1024 x 768, 30fps is what I use
  2. Add the background shape to enable TUIO to recognize your touching the stage
  3. Now Make a new MovieClip You want to be pulled from the Library, I named mine "libraryItem"
  4. Open the "Linkage..." properties for that MovieClip in the Library
  5. Select "Export for Actionscript" and name the Class "libraryItem"
    • This will make sure the AS file can grab this MovieClip dynamically
  6. Now we make the AS file. I named mine "PressAndAppear.as"
    • We will put that in this folder structure: app/demo/MyTouchApp
    • and link to it in the Flash File: In the 'Document Class' enter "app.demo.MyTouchApp.PressAndAppear"

I'll let you get that all setup. It should be similar to my previous tutorials.

Let's DO THIS!

but, I'm not sure how I'd like to show you the code this time. Hmm, alright I'll give you my first successful attempt but not the final code just yet. I want to talk something through with you all.

package app.demo.MyTouchApp{
 
	import flash.events.TUIO;
	import flash.events.TouchEvent;
	import flash.display.*;
 
	public class PressAndAppear extends Sprite {
 
		public function PressAndAppear():void {
			//--------connect to TUIO-----------------
			TUIO.init(this,'127.0.0.1',3000,'',true);
			addEventListener(TouchEvent.MOUSE_MOVE, onTouchMove);
			addEventListener(TouchEvent.MOUSE_DOWN, onTouchDown);
			addEventListener(TouchEvent.MOUSE_UP, onTouchUp);
 
		}
		public function onTouchDown(e:TouchEvent):void {
			var dynamicObj:MovieClip = new libraryItem();
			dynamicObj.name = e.ID.toString();
			dynamicObj.x = e.localX;
			dynamicObj.y = e.localY;
			addChild(dynamicObj);
		}
		public function onTouchUp(e:TouchEvent):void {
			var target:DisplayObject = getChildByName(e.ID.toString());
			removeChild(target);
		}
		public function onTouchMove(e:TouchEvent):void {
			var target:DisplayObject = getChildByName(e.ID.toString());
			target.x = e.stageX;
			target.y = e.stageY;
		}
	}
}

Now by all accounts, this will work...to a point.

			addEventListener(TouchEvent.MOUSE_MOVE, onTouchMove);
			addEventListener(TouchEvent.MOUSE_DOWN, onTouchDown);
			addEventListener(TouchEvent.MOUSE_UP, onTouchUp);

We have out 3 event listeners. onTouchDown will pull the movieclip from the library and add it to the stage, it also names the libraryItem the same name as the blob ID that it should track. onTouchMove gets the intended MovieClip via getChildByName which matches the ID of the blob that should have created it. Piece of cake. onTouchUp works similar to onTouchMove where it gets the intended MovieClip via getChildByName and will just remove the MovieClip all together. Done. BUT not done.

Test it.

leftoversAnd touch and lift up a lot of touch points at the same time.

You see what I saw right? There are now a LOT of leftover MovieClips. Now why is this? I'm not 100% positive, but here is my best guess. When any of the touch events are ran inside of the TUIO files, there is quick a bit of information to go through. But it doesn't just queue up everything and wait for an event to finish, should it be updated, at any given moment, whichever event is running is canceled and replaced by the new event that is happening.  Or it could have something to do with bubbling, I'm really not sure, but what I have concluded is that onTouchUp is not reliable enough to use easily.

We need to adjust our thinking just a little bit for something much more stable. Instead of having the stage listen to TouchEvent.MOUSE_UP, what we can do is have the Movie Clip itself check to see if the blob it's supposed to be tracking is still alive, if it's not, remove itself.

Lets revise a bit

package app.demo.MyTouchApp{
 
	import flash.events.TUIO;
	import flash.events.TouchEvent;
	import flash.events.Event;
	import flash.display.*;
 
	public class PressAndAppear extends Sprite {
 
		public function PressAndAppear():void {
			//--------connect to TUIO-----------------
			TUIO.init(this,'127.0.0.1',3000,'',true);
			addEventListener(TouchEvent.MOUSE_MOVE, onTouchMove);
			addEventListener(TouchEvent.MOUSE_DOWN, onTouchDown);
		}
		public function onTouchDown(e:TouchEvent):void {
			var dynamicObj:MovieClip = new libraryItem();
			dynamicObj.name = e.ID.toString();
			dynamicObj.x = e.localX;
			dynamicObj.y = e.localY;
			addChild(dynamicObj);
			dynamicObj.addEventListener(Event.ENTER_FRAME, checkForRemoval);
		}
		public function onTouchMove(e:TouchEvent):void {
			var target:DisplayObject = getChildByName(e.ID.toString());
			target.x = e.stageX;
			target.y = e.stageY;
		}
		public function checkForRemoval(e:Event):void {
			if (!TUIO.getObjectById(e.target.name)) {
				e.target.removeEventListener(Event.ENTER_FRAME, checkForRemoval);
				removeChild(e.target as MovieClip);
			}
		}
	}
}

Now that onTouchUp is removed, we need something to know when to remove the MovieClips, so we use the MovieClips themselves

			dynamicObj.addEventListener(Event.ENTER_FRAME, checkForRemoval);

This runs checkForRemoval so long as the Movie Exists on the stage

		public function checkForRemoval(e:Event):void {
			if (!TUIO.getObjectById(e.target.name)) {
				e.target.removeEventListener(Event.ENTER_FRAME, checkForRemoval);
				removeChild(e.target as MovieClip);
			}
		}

intendedAnd we can utilize data inside of TUIO with an original function inside of it: getObjectById() and since I named the movie clip with the intended blob for it to track all is needs to do is keep checking if that blob still exists. One the blob is removed from the stage, that blob's Id will NEVER return again so all we have to do is remove the ENTER_FRAME event and remove the object from the stage. And if I remember correctly the removed items should also eventually get garbage collected and cleared from memory when Flash deems necessary.

There you have it. Each touch point gets it's own Movie Clip which is pulled from the library, follows the same touch point and removes itself when the touch point is removed. And the code remains as simple as i can make it so you all can use it as a starting point.

My Google Code Page has been updated to include this new tutorial, for those you stay up to date with SVN.

Tags: , , , ,

7 Responses to “Add, Move and Remove MovieClip from Library via Touch Point”

  1. Simpleex says:

    Thought you made my day but… 1067 errors on compile.

    I replaced :
    dynamicObj.name = e.ID;
    by
    dynamicObj.name = e.ID.toString();

    and
    var target:DisplayObject = getChildByName(e.ID);
    by
    var target:DisplayObject = getChildByName(e.ID.toString());

    It corrects 2 on 3 !

    But still have error on removeChild(e.target)

    1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject.

  2. Simpleex says:

    Finally got it to work here with : removeChild(e.target as MovieClip);

    Do not exactly know why it losts variable type but it works now !!

    Thanks again !!

  3. Chris Yanc says:

    Thanks for the catch Simpleex, I didn’t have Strict Mode on when I was coding.

  4. Ex Girlfiend says:

    Not that I’m totally impressed, but this is a lot more than I expected when I found a link on SU telling that the info is awesome. Thanks.

  5. Rupert says:

    Hi there.

    Some great work looking into TUIO / Flash possibilities!

    I have been down a similar route to yours with “Add, Move and Remove MovieClip from Library via Touch Point” method. Although I have noticed some poor performance with this method when testing with SimTouch and other TUIO simulators. After about 5-10 seconds the movieclip stops dragging and only occasionally picks up the point again.

    My solution was to use the RotatableScalable class and add the movieclip into a RotatableScalable object. I am using a PNG sequence particle effect for the object with additional connectors (like your cats cradle).

    This works great but I have stumbled across the inevitable problem. The touch is still invoked on the “onTouchDown” listener event and adds an object to the screen, but the touch to add the object to the screen has no relation to the RotatableScalable object added. The RotatableScalable object can be dragged but this is independant to the original touch. You have to remove the original touch (a double click to create permanent multiple touchs in SimTouch) in order to remove the RotatableScalable object.

    In conclusion, im close but no cigar. Do you know of any way to translate the initial touch to the placed object? Or even simply a way of artificially removing and adding a touch in order to make a visually “seemless” contact with the object below?

    Bit of a rant I know, but im just wondering if you would know.

    Many thanks

    Rupert

  6. Sha says:

    Hi Christopher,

    This is a helpful tutorial and your site is cool. I want to ask is there a way to touch objects on stage and move it to another object to play a movie clip similar to hit test?

    Thanks

    Sha

  7. Chris Yanc says:

    The easiest way off the top of my head is that you can attach something like RotatableScalable to the movie clip you want to move around. And then add a TouchEvent.MOUSE_UP listener that does the hitTest functionality.

Leave a Reply

fans of cyancdesign

What do you all think?

What developer tool[s] do you use to compile your SWF files?

View Results

Loading ... Loading ...

Shameless Attempts to Pay the Bills