Skip to main content
Inspiring
August 16, 2011
Question

Bug fix requires switching touch events from symbols/classes to the main stage?

  • August 16, 2011
  • 2 replies
  • 1469 views

Also posted in Mobile Development, I'm still not sure which forum I should be in.

For previous threads:

http://forums.adobe.com/thread/864057

http://forums.adobe.com/thread/863566

http://forums.adobe.com/thread/864262

http://forums.adobe.com/thread/863597


Bug ID #2940816

I  have an app that wasn't compiling correctly. I sent the bug to Adobe  who responded with a workaround. However, I can't figure out how to make  their stated workaround work in my code.

I have puzzle  pieces on the stage. Each is assigned to a separate class. Inside the  class I have touch events defining multiple touch events for each piece.

I  have another spot on the stage where, when it is touched, a puzzle  piece appears. These are also each linked to a separate class. Inside  this class I also have touch events defining multiple touch events for  each piece.

Though it works fine on my computer, it wasn't  working on an iPad. Adobe said that I needed to switch the touch events  so that they were assigned to the main stage instead of to each  individual object.

However, the code they gave me didn't really make sense in context and I'm confused how to implement it.

This is the code in the class for each piece that is created when you touch the stage:

        public function GeoPiece(): void {
            if (PuzzleGlobals.currentLevel == "Name") {
                this.gotoAndStop("wholeName");
            }
            else if (PuzzleGlobals.currentLevel == "Abbrev") {
                this.gotoAndStop("abbrev");
            }
            else if (PuzzleGlobals.currentLevel == "Shape") {
                this.gotoAndStop("shape");
            }
            this.addEventListener(TouchEvent.TOUCH_MOVE, geoPieceBegin);
        }
       
        public function geoPieceBegin (e:TouchEvent): void {
            PuzzleGlobals.pieceActive = true;
            e.target.startTouchDrag(e.touchPointID, false);
            e.target.addEventListener(TouchEvent.TOUCH_END, geoPieceEnd);
            e.target.interactionBegin();
            MovieClip(this.parent.parent).nameDisplay.gotoAndStop(e.target.abbrev );
            PuzzleGlobals.currentPiece = e.target.abbrev;
        }
       
        public function geoPieceEnd (e:TouchEvent): void {
            PuzzleGlobals.pieceActive = false;
            if (currentObjOver.isLocked == true) {
                currentObjOver.gotoAndStop ("Lock");
            }
            else {
                currentObjOver.gotoAndStop ("Out");
            }
            MovieClip(this.parent.parent).nameDisplay.gotoAndStop(PuzzleGlobals.c hosenPuzzle);
            e.target.stopTouchDrag(e.touchPointID);
            if (this.dropTarget.parent is GeoPuzzle) {
                if (GeoPuzzle(this.dropTarget.parent).abbrev == e.target.abbrev) {
                    PuzzleGlobals.statesCompletedUSA++;
                    GeoPuzzle(this.dropTarget.parent).isLocked = true;
                    GeoPuzzle(this.dropTarget.parent).gotoAndStop("Lock");
                    e.target.parent.removeChild(DisplayObject(e.target));
                }
                else {
                    //play BOOP sound indicated wrong drop;
                }
            }
            if (PuzzleGlobals.statesCompletedUSA == PuzzleGlobals.TOTAL_NUMBER_USA) {
                //play fireworks game
            }
            else {
                //do nothing
            }
            e.target.removeEventListener(TouchEvent.TOUCH_END, geoPieceEnd);
        }
       
        public function interactionBegin () {
             if (this.dropTarget != null && this.dropTarget.parent is  GeoPuzzle) { //check to make sure it's over a puzzle piece
                currentObjOver = GeoPuzzle(this.dropTarget.parent);
                currentObjOver.gotoAndStop("Over");
            }
            if (lastObjOver != currentObjOver) {
                if (lastObjOver.isLocked == true) {
                    lastObjOver.gotoAndStop("Lock");
                }
                else {
                    lastObjOver.gotoAndStop("Out");
                }
                lastObjOver = currentObjOver;
            }
        }

This is the code in the class for each piece that's already on the stage:

        public function GeoPuzzle(): void {
            if (this.isLocked == true) {
                this.gotoAndStop ("Lock");
            }
            if (PuzzleGlobals.pieceActive == true) {
                this.addEventListener(TouchEvent.TOUCH_BEGIN, geoPuzzleBegin);
            }
        }
               
        public function geoPuzzleBegin (e:TouchEvent): void {
            e.target.addEventListener(TouchEvent.TOUCH_END, geoPuzzleEnd);
            e.target.gotoAndStop("Over");
            MovieClip(this.parent).nameDisplay.gotoAndStop(e.target.abbrev);
        }
       
        public function geoPuzzleEnd (e:TouchEvent): void {
            if (e.target.isLocked == false) {
                e.target.gotoAndStop("Off");
            }
            else if (e.target.isLocked == true) {
                e.target.gotoAndStop("Lock");
            }
            MovieClip(this.parent).nameDisplay.gotoAndStop(PuzzleGlobals.chosenPu zzle);
            e.target.removeEventListener(TouchEvent.TOUCH_END, geoPuzzleEnd);
        }

You  can see that each piece (whether it's already locked on the stage or  movable) reacts differently to different touch events. However, this is  the code that Adobe gave me as a workaround:

this.stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchEvent);
this.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchEvent);
this.stage.addEventListener(TouchEvent.TOUCH_END, onTouchEvent);

var beginCount:uint=0;
var moveCount:uint=0;
var endCount:uint=0;

function onTouchEvent(event:TouchEvent):void{
     switch (event.type){
          case TouchEvent.TOUCH_BEGIN:
           &nbs p;           &n bsp; trace("BEGIN")
           &nbs p;           &n bsp; beginCount++;
           &nbs p;           &n bsp; square.x = event.stageX;
           &nbs p;           &n bsp; square.y = event.stageY;
           &nbs p;           &n bsp; square.startTouchDrag(event.touchPointID, false);
           &nbs p;           &n bsp; break;
          case TouchEvent.TOUCH_MOVE:
           &nbs p;           &n bsp; trace("MOVE")
           &nbs p;           &n bsp; moveCount++;
           &nbs p;           &n bsp; break;
          case TouchEvent.TOUCH_END:
           &nbs p;           &n bsp; trace("END")
           &nbs p;           &n bsp; endCount++;
           &nbs p;           &n bsp; square.stopTouchDrag(event.touchPointID);
           &nbs p;           &n bsp; break;
     }
     trace("begin: "+beginCount+" move: "+moveCount+" end: "+endCount);
//     countText.text = "begin: "+beginCount+" move: "+moveCount+" end: "+endCount;
}

This  doesn't make any sense to me because it seems that it would only work  if touching the stage had to react in just a single way. I have multiple  pieces that need to each react differently.

1. The pieces that are locked to the stage need to highlight when touched and display their name.

2.  These pieces also need to keep themselves highlighted and their names  displayed when the touch is dragged off of them instead of just removed.

3.  Each piece needs to be created when touching the Puzzle Piece button  the stage. As these pieces are dragged, they need to highlight the  pieces underneath them and unhighlight them when they are dragged off.  They also need to display their own names, and lock into place when they  are dragged over the correct piece.

My questions are:

1. Why don't touch events work in the compiler?

2. How can I translate my current working code's touch events to all be directly linked to the stage instead of their objects?

Thanks so much!

Amber

This topic has been closed for replies.

2 replies

AmbariAuthor
Inspiring
August 29, 2011

I am going to copy and paste this answer into all of the forums I've asked this question in case some noob like me comes along and needs the answer.

I found the problem! After 3 months I finally figured out what was wrong and why my app was working in Device Central when exported as Flash 10.1 and not on my iPad when exported as AIR for iOS.

The problem is that in the Flash runtime, if a line of code returns a bug, the flash runtime says "Error, shmerror, try again next time." So I had one if, else statement that was executing when it wasn't supposed to be - only once, at the very beginning of the program. It was throwing an error. When I exported as Flash, flash didn't care, and still executed the code later when it was supposed to. But Apple won't let their programs crash. So instead of just trying that code again, Apple decided, after the first error was thrown, that it would then COMPLETELY IGNORE that line of code. So the error was in the line where the states would unhighlight themselves. Apple just shut down that line of code, that's why it wouldn't execute properly.

I ended up changing this line of code

if (lastObjOver != null && lastObjOver.isLocked == true)

which threw an error when the piece was FIRST dragged over the puzzle, to to this

if (lastObjOver.parent != null && lastObjOver.isLocked == true)

which wouldn't throw the error.

Problem solved!

If anyone else is having this problem, I suggest you do what I did. Change all your touch events to mouse events so you can run the program in the adc debugger. That's when I discovered the error being thrown.

chris.campbell
Legend
August 17, 2011

Hi Amber,

I don't know the answers, but I'm going to try and find someone to follow up with you.

Thanks,

Chris

AmbariAuthor
Inspiring
August 17, 2011

Thanks so much, Chris!

Pahup
Adobe Employee
Adobe Employee
August 23, 2011

Ambari,

Regarding the problem that you stated that touch end events are not always equal to the begin events.

That's happening in your sample application (attached to the bug) because, when sprite is moved very fast, finger does not actually gets picked up from the sprite, that's why you do not receive the touch end event and which is as expected.

To receive an end event from a sprite, your finger needs to be on the sprite when you lift it, that's why as a workaround it was suggested to use listeners on stage.

However I see that in your actual application, you have multiple pieces and you can not listeners to stage.

In that case, I think user will have to make sure that finger gets lifted from sprite only.

Thanks

-Pahup