UStream Not Live

cyancdesign: blog

Tutorial: Blob Lines

There are two ways to work with multiple touch point that come to mind when developing multi-touch applications. One is to attach TouchEvents to the objects which are applied to the stage. The other is to use the array of blobs to build interaction between the blob points. In this tutorial I'd like to go over a basic setup you can use to communicate through the blob array, by drawing lines through all of the blobs that a activated on the stage. This app is built using the Touchlib classes for multi-touch communication with tBeta or Touchlib via FLOSC.

If you do not have the needed Touchlib files, you can find them here: http://code.google.com/p/touchlib/
by downloading touchlib-src-win32-20071106.zip from the download page, or downloading the source code via SVN in the Source section.

So begin with creating a new folder, i named mine "blobLines" and create a new Flash file, which I've named blogLines.fla
Then create another folder named "BlobsFunction" (this is case sensitive) in the "blobLines" folder, this will contain the AS file of the application.

Find the folder labeled "flash" from the Touchlib files, normally found in /AS3/int/
And copy this folder to your "blobLines" folder. This contains the TUIO classes needed for Flash to communicate with tBeta and Touchlib via FLOSC.

So now your "blobLines" folder should have: blogLines.fla, a folder labeled "flash" and a folder labeled "BlobsFunction"

Open the Flash file and set size setting to you screen's resolution, I use a 1024x768 size display, and change your framerate to 30fps.
Now open a new file, and create a new Actionscript file. Save as... BlobLines.as (this is case sensitive)

Enter the inital code into the BlobLines.as file:

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. public class BlobLines extends Sprite {
  4. public function BlobLines():void {
  5. trace("BlobLines.as Loaded");
  6. }
  7. }
  8. }

Back in the blogLines.fla, in the document's Properties panel, find the Document Class field and type in: BlobsFunction.BlobLines
This connects blogLines.fla to BlobLines.as.

Test your movie.
You should see: "BlobLines.as Loaded" appear in your Output Panel

Now we need to add the TUIO class to BlobLines.as
So back in BlobLines.as, the code changes to this:

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. import flash.events.TUIO;
  4. public class BlobLines extends Sprite {
  5. public function BlobLines():void {
  6. TUIO.init(this,'127.0.0.1',3000,'',true);
  7. }
  8. }
  9. }

import flash.events.TUIO; connects BlobLines.as to TUIO.as.
Then in the BlobLines function, the code it added to start the TUIO communication when the app runs.

Test the movie again, you should see the white, red and green squares in the upper left corner, the touch information in the upper right, and circles where you touch on the stage.

So, everything it ready to go. Now we need a solution to gather the touch information into an array. We could create an array in BlobLines.as, and on every touch down add that blob to the array, then on a touch up remove the blob from an array, and on a touch movement update all the information in that array. We could do that, and I've done that before, it's not a pleasent thing to write. BUT! I just so happens that TUIO.as actually contains that information in an array, OBJECT_ARRAY, and is much easier to pass through to our AS file than one may think. And since TUIO.as is gathering the information directly from FLOSC, it seems to me that it is more reliable and accurate to work with.

So how do we do that? We need to add a little something to flash/events/TUIO.as
lets open that file.

Now first thing I want to mention is that OBJECT_ARRAY is a private variable. The creator of this file intended only for this AS file to be able to change that value. Which makes sense, you don't want some rogue function changing value in the array when your trying to use it specifially for multitouch objects. But, we dont want to change it, we only want to be able to get the value at any time. So, around line 119 or so, add in this function.

  1. public static function returnBlobs():Array{
  2. return OBJECT_ARRAY;
  3. }

Save the file and return to BlobLines.as
Now we want to test that the information we want is coming through.
so try this code:

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. import flash.events.TUIO;
  4. import flash.events.Event;
  5. public class BlobLines extends Sprite {
  6. public function BlobLines():void {
  7. TUIO.init(this,'127.0.0.1',3000,'',true);
  8. addEventListener(Event.ENTER_FRAME, test_returnBlobs);
  9. }
  10. public function test_returnBlobs(e:Event):void {
  11. trace(TUIO.returnBlobs().length);
  12. }
  13. }
  14. }

What has been added/changed?
addEventListener(Event.ENTER_FRAME, test_returnBlobs); is added to run a function every frame to do so, import flash.events.Event; needs to be added to the imports so this AS file knows what Event.ENTER_FRAME is. and the function is added to trace TUIO.returnBlobs()

Test the Movie.
You should see the number of touch points on the screen for each frame displayed in the document's Properties panel.

This is good, one we have this information coming through, we can begin using however we need to. So lets do something simple draw a line from the top left corner of the stage to each blob. We'll start with the down touch.

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. import flash.display.Shape;
  4. import flash.events.TUIO;
  5. import flash.events.TouchEvent;
  6. public class BlobLines extends Sprite {
  7. private var my_line:Shape = new Shape();
  8. public function BlobLines():void {
  9. TUIO.init(this,'127.0.0.1',3000,'',true);//begins TUIO communication
  10. addEventListener(TouchEvent.MOUSE_DOWN, touchDown);
  11. }
  12. public function touchDown(e:TouchEvent):void {
  13. for (var i=0; i < TUIO.returnBlobs().length; i++) {
  14. addChild(my_line);
  15. my_line.graphics.lineStyle(10, 0xF46000);
  16. my_line.graphics.moveTo(0, 0);
  17. my_line.graphics.lineTo(TUIO.returnBlobs()[i].x,TUIO.returnBlobs()[i].y);
  18. }
  19. }
  20. }
  21. }

Let's break it down,
import flash.display.Shape; has been added to be able to use the graphics fuctions in Flash.
import flash.events.TouchEvent; (contained in ) has been added to be able to write TouchEvent.MOUSE_DOWN.
addEventListener(TouchEvent.MOUSE_DOWN, touchDown); runs the touchDown function which draws a new line from point 0,0 to each blob in that array by

looping through all of the TUIO.returnBlobs() objects.

Test the movie,
you should see the lines appear, but they do not move, and they do not go away. Before we run the loop in the touchDown, we need to reset the graphic lines.
we change the function to:

  1. public function touchDown(e:TouchEvent):void{
  2. my_line.graphics.clear();
  3. for (var i=0; i < TUIO.returnBlobs().length; i++) {
  4. addChild(my_line);
  5. my_line.graphics.lineStyle(10, 0xF46000);
  6. my_line.graphics.moveTo(0, 0);
  7. my_line.graphics.lineTo(TUIO.returnBlobs()[i].x,TUIO.returnBlobs()[i].y);
  8. }
  9. }

We are getting closer. Now we need to apply this exact same functionality to the touch up and the touch movement. This gives the visual illusion of animation on the stage for all the lines, even though we are only drawing lines and erasing they very very quickly.

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. import flash.display.Shape;
  4. import flash.events.TUIO;
  5. import flash.events.TouchEvent;
  6. public class BlobLines extends Sprite {
  7.  
  8. private var my_line:Shape = new Shape();
  9.  
  10. public function BlobLines():void {
  11.  
  12. TUIO.init(this,'127.0.0.1',3000,'',true);
  13.  
  14. addEventListener(TouchEvent.MOUSE_DOWN, touchDown);
  15. addEventListener(TouchEvent.MOUSE_UP, touchUp);
  16. addEventListener(TouchEvent.MOUSE_MOVE, moveUpdate);
  17. }
  18. public function updateCall():void {
  19. my_line.graphics.clear();
  20. for (var i=0; i < TUIO.returnBlobs().length; i++) {
  21. addChild(my_line);
  22. my_line.graphics.lineStyle(10, 0xF46000);
  23. my_line.graphics.moveTo(0, 0);
  24. my_line.graphics.lineTo(TUIO.returnBlobs()[i].x,TUIO.returnBlobs()[i].y);
  25. }
  26. }
  27. public function touchDown(e:TouchEvent):void {
  28. updateCall();
  29. }
  30. public function touchUp(e:TouchEvent):void {
  31. updateCall();
  32. }
  33. public function moveUpdate(e:TouchEvent):void {
  34. updateCall();
  35. }
  36. }
  37. }

Take the code we used for erasing and creating the lines, and pull it out into it's own function updateCall(). Then apply all three types of the necessary touch events; TouchEvent.MOUSE_DOWN, TouchEvent.MOUSE_UP, TouchEvent.MOUSE_MOVE, to call updateCall(). So, whenever the flash need to do it's "animation" would only be when something touching the stage changes, but adding a touchpoint, removing one, or moving any of them.

There is only one this left. currently, when you touch the stage, the remove all the touches again, there is usually one left over line. When the last touch up function runs, there is still one remaining touchObject in the OBJECT_ARRAY being refferenced. So the very last TouchEvent.MOUSE_UP need just one extra graphic.clear() to empty the stage, if it is indeed the last blob to be removed:

  1. package BlobsFunction{
  2. import flash.display.Sprite;
  3. import flash.display.Shape;
  4. import flash.events.TUIO;
  5. import flash.events.TouchEvent;
  6. public class BlobLines extends Sprite {
  7. private var my_line:Shape = new Shape();
  8. public function BlobLines():void {
  9. TUIO.init(this,'127.0.0.1',3000,'',true);
  10. addEventListener(TouchEvent.MOUSE_DOWN, touchDown);
  11. addEventListener(TouchEvent.MOUSE_UP, touchUp);
  12. addEventListener(TouchEvent.MOUSE_MOVE, moveUpdate);
  13. }
  14. public function updateCall():void {
  15. my_line.graphics.clear();
  16. for (var i=0; i < TUIO.returnBlobs().length; i++) {
  17. addChild(my_line);
  18. my_line.graphics.lineStyle(10, 0xF46000);
  19. my_line.graphics.moveTo(0, 0);
  20. my_line.graphics.lineTo(TUIO.returnBlobs()[i].x,TUIO.returnBlobs()[i].y);
  21. }
  22. }
  23. public function touchDown(e:TouchEvent):void {
  24. updateCall();
  25. }
  26. public function touchUp(e:TouchEvent):void {
  27. updateCall();
  28. if (TUIO.returnBlobs().length == 1) {
  29. my_line.graphics.clear();
  30. }
  31. }
  32. public function moveUpdate(e:TouchEvent):void {
  33. updateCall();
  34. }
  35. }
  36. }

That would be all for this one my friends.
I hope this has made sense, worked for you and inspires you to move forward in your Multi-touch Flash projects.

and here's a little added fun, replace the loop with this code, and you have my Cat's Cradle app:

  1. if (TUIO.returnBlobs().length >= 2) {
  2. for (var i=0; i < TUIO.returnBlobs().length; i++) {
  3. addChild(my_line);
  4. my_line.graphics.lineStyle(10, 0xF46000);
  5. my_line.graphics.moveTo(TUIO.returnBlobs()[i].x,TUIO.returnBlobs()[i].y);
  6. if (TUIO.returnBlobs()[i+1] != undefined) {
  7. my_line.graphics.lineTo(TUIO.returnBlobs()[i+1].x,TUIO.returnBlobs()[i+1].y);
  8. //Line.graphics.lineTo(blobs[i+1].e.stageX,blobs[i+1].e.stageY);
  9. } else {
  10. my_line.graphics.lineTo(TUIO.returnBlobs()[0].x,TUIO.returnBlobs()[0].y);
  11. //Line.graphics.lineTo(blobs[0].e.stageX,blobs[0].e.stageY);
  12. }
  13. }
  14. } else if (TUIO.returnBlobs().length == 1) {// Makes new Start Point for lines
  15. my_line.graphics.moveTo(TUIO.returnBlobs()[0].x,TUIO.returnBlobs()[0].y);
  16. }

Source Files: Blob Lines

More Available at: http://code.google.com/p/multitouchas3experiments/

Tags: , , , ,

3 Responses to “Tutorial: Blob Lines”

  1. anirudh says:

    great tutorial chris ! tried and applied the above techniques. Surely it cuts down the time required to get up and running with as3 -multitouch.

  2. Simplex says:

    Nice tutorial !

    I have still a problem and need help !!

    I just want to put a Movieclip under each blob, move each Movieclip when blobs move AND remove the Movieclip when blob is away (just like the outines on tbeta calibration screen). It must be simple but I don’t get it !!

    Could U guide ??

    Thx from a flashnoob…

  3. johnRoger says:

    Hi Mr. Christopher. I’m learning to program on actionscript3, with flash platform, and your site is very useful. For tihs tutorial, I used the SVN touchlib packages, and except a circle, nothing is visible.. I think the “problem” is in the library, becuase in the line 119, the function you suggest to add, is already added.. Thanks.

Leave a Reply

You must be logged in to post a comment.