TouchEvent.TOUCH_BEGIN, onTouchBegin Freezes after several Reloads
Asked Answered
I

1

7

I am building an Adobe Air AS3 IOS and Android App, in which i have a movie clip in the center of the stage. When you start touching this movie clip, you can move it all around the stage.
This is how i'm doing so :

            Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
            MC_M1.alpha = 1;
            MC_M1.addEventListener(Event.ENTER_FRAME, ifHitAct);
            MC_M1.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
            MC_M1.x = 0.516 * gameIntro.stageWidthToUse;
            MC_M1.y = 0.75 * gameIntro.stageHeightToUse;
            MC_M1.height = 0.2 * gameIntro.stageHeightToUse;
            MC_M1.width = MC_M1.height / 1.4;
            gameIntro.STAGE.stage.addChildAt(MC_M1,1);

function onTouchBegin(event:TouchEvent)
        {
            trace("TouchBegin");
            if (touchMoveID != 0)
            {
                trace("It Did Not");
                return;
            }
            touchMoveID = event.touchPointID;

            gameIntro.STAGE.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
            gameIntro.STAGE.stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
        }
        function onTouchMove(event:TouchEvent)
        {
            if (event.touchPointID != touchMoveID)
            {
                return;
            }
            //trace("Moving")
            MC_M1.x = event.stageX;
            MC_M1.y = event.stageY;
        }
        function onTouchEnd(event:TouchEvent)
        {
            if (event.touchPointID != touchMoveID)
            {
                return;
            }
            //trace("Ending");
            touchMoveID = 0;
            gameIntro.STAGE.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
            gameIntro.STAGE.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
        }

When the player actually looses the game, what i am actually doing is the following :

MC_M1.removeEventListener(Event.ENTER_FRAME , ifHitAct);
MC_M1.removeEventListener(TouchEvent.TOUCH_BEGIN , onTouchBegin);
gameIntro.STAGE.stage.removeChild(MC_M1);
MC_M1.alpha = 0;
isDead = 1;
replayButToUse.x = 0.127 * gameIntro.stageWidthToUse;
replayButToUse.y = 0.91 * gameIntro.stageHeightToUse;
replayButToUse.addEventListener(MouseEvent.CLICK, gotoIntro);

This is all happening in a class called : introClassToUse.
So when the users looses, he will get a replay button, and when he clicks it, he will go back to the same class and reload everything, using the following code :

function gotoIntro(event:MouseEvent):void
        {

            replayButToUse.removeEventListener(MouseEvent.CLICK, gotoIntro);
            replayButToUse.alpha = 0;
            replayButToUse.removeEventListener(MouseEvent.CLICK, gotoIntro);
            stop();
            var reload:introClassToUse = new introClassToUse();

        }

And so everything loads back up and the game restarts. My problem is, i'm facing a very weird behavior when i tend to replay the game more than 2-3 times. The MC_M1 just stops listening to any touch event, but keeps on listening to ENTER_FRAME events, in which i keep touching the MC_M1 but it seems to not respond to it. I even debugged it remotely from my iPhone, for the first couple of replays, i can see the trace("TouchBegin"); with it's outcome, it was showing me TouchBegin, but after a few replays, the touch events just froze. What am i missing?

Any help is really appreciated, i'm new in AS3, i need to learn so i could manage more

Edit 1 :

I have no code on any frame, i just have lots of AS Classes. The fla file is linked to an AS Class called gameIntro. In this class, i have linked the following :
- STAGE is an object of type Stage.
- gameIntro.STAGE = stage
Later on, when the user clicks a play button, i call the class introClassToUse. This class has all the game functionalities. All the code present above is in introClassToUse. When the user looses and clicks the replay button, he will go to "goToIntro" function, im which i recall the introClassToUse.
It's all working fine, with several other timers implemented and all, the only problem is that after several replays, the MC_M1 just freezes over I am removing the MC_M1 each time the user looses and re-add them when i call back the introClassToUse, because i tried to use the .visible property, it didn't work at all ( this is why i am using the gameIntro.STAGE.stage.removeChild(MC_M1)

Illuminometer answered 16/8, 2016 at 17:19 Comment(16)
Unless you're doing something I don't get, I think you should do things differently. Use visible to show and hide clips so you don't have to add and remove clips and listeners - if visible=false no touch event. You should have one set of main touch events on stage that run everything. Assign begin and end touch events to clips to simply know when they're being touched. So the stage touch_move listener just checks to see if MC_M1 is being touched. This way everything in your app shares one set of touch events and you don't have to add and remove clips and listeners. Make sense?Script
I've tried it..i still get the same result..what do you think is happeningIlluminometer
Is it reproduced if you change touch to mouse events and test on the desktop computer?Chiromancy
I'm quite new in as3, i read somewhere that i need the touch events for this kind of results..what do you suggest @ChiromancyIlluminometer
I'd suggest changing TOUCH_BEGIN to MOUSE_DOWN, TOUCH_END to MOUSE_UP, TOUCH_MOVE to MOUSE_MOVE (note that MouseEvent doesn't have touchPointID) — and checking if the issue persistsChiromancy
@Chiromancy i already did that before using the touchEvents, the problem was that the MC sometimes just stops moving on the stage, and the game consists that the user always touches the MC and keeps moving it all the time, that's why i changed to touchEvents. So i can't change to see if the problem persists since the basic functionality won't take place to start with!..What do you think?Illuminometer
I was thinking about using startDrag instead of TOUCH_MOVE event handling, but if the TouchBegin trace is not seen, the problem is somewhere else. Seems like MC_M1 gets mouseEnabled = false or its parent get mouseChildren = false or something like that. I'd suggest two things: adding a TOUCH_BEGIN listener to the stage with a single trace in it and creating a minimum example to reproduce the issueChiromancy
How can i make sure that the MC is always touch enabled? Maybe that will fix the issue?Illuminometer
The reference on startTouchDrag mentions a touch-enabled device, not a Sprite. So I'd suggest checking if a TOUCH_BEGIN listener added to stage will trace("stage touch") when MC_M1 is not getting draggedChiromancy
@Chiromancy Yes i will get stage touch even if the mc froze and i try to touch itIlluminometer
I'd suggest adding all touch listeners to the stage and checking if MC_M1 is touched using getObjectsUnderPoint().Chiromancy
i don't think this is helping..is there any other reason causing this problem?Illuminometer
@EliasRahme, don't worry you might get a solution during the "grace period" (extra 24 hrs added if no answer). Is your code on different frames? It might help if logic is controlled from one central place. Anyways how to recreate your issue? Is it enough to just make a shape on stage and use your code? Also how to recreate the "lose game" situation. Explain this gameIntro.STAGE.stage.removeChild(MC_M1); so is gameIntro containing MC called STAGE but what is other stage? I will try to recreate later but can only test on Android not iPhone.Kktp
@Kktp please check my edit, and thank you for replying!Illuminometer
Unfortunately I cannot re-create your issue. The touch events work for me always (tried over 10 replays). This was on Android tablet and my code was different (more basic). I will adjust it later to match your code setup. If this adjust should also work for me, I will pass the AS files for you to compile for iPhone. PS: I wonder if its a hardware/OS bug... Does your code work fine when compiled for Android?Kktp
@Kktp Thank you ! it's really bizarre and weird, sometimes after 15 times, i will get this behavior , sometimes after 5 times. I will test it on android and get back to you. It's pretty weird and actually really frustrating!!Illuminometer
C
1

I know the question is old but maybe someone is still wondering what is going on here (like me). There are lot of problems in you code but I thing the root of your problem starts here:

function gotoIntro(event:MouseEvent):void{
    //...
    var reload:introClassToUse = new introClassToUse();
}
  • It is usually unwanted behavior if simply creating an instance does more than nothing to your program and you don't even need to assign it to variable in this case.
  • You mentioned this code is located in your introClassToUse class. This basically means that you are creating new instance of your game inside old one and this seem to be completely awry.

You should consider using only instance properties in your class definition and create new introClassToUse() in external classes;

You didn't include many important details about your code like

  • How the whole class structures look like - for example you can't place line like MC_M1.addEventListener(Event.ENTER_FRAME, ifHitAct);in the scope of your class so obviously you have this in some function and we don't know when and from where it is called.

  • Where and how your variables are declared, and assigned. It's hard to tell if your MC_M1 is property of an instance or a class, is it internal/public/private/...

  • Do you link library symbols to your classes or acquire it from stage.

There could be many things that could give you such result. Based on what you wrote I've reproduced behavior similar to what you've describe but using mouse event and a dummy loose condition. This ends the game each time you drop the mc partially outside right edge of the sage, show restart button and starts again if you click it (basically it's mostly your code). It works fine for about 10s and than suddely you can't move the mc anymore. The frame event is still tracing out but touch/mouse is not.

How can it be? I suspect that you could remove only listeners somewhere and have invisible mc stuck on the new one. And this could be easy overlooked, especially if you using static properties. Again we don't even know where is your movie clip coming from so we can only guess what is happening whit your code but I've tried to take the example simple this is how I did it. The problem may lay in some completely different place but you can guess for all scenarios.

Document class of the project - GameIntro.as

package 
{
    import flash.display.Sprite;

    public class GameIntro extends Sprite 
    {
        //Document class. this need to be compiled with strict mode off.
        public function GameIntro() {

            GameIntro.STAGE = stage;
            GameIntro.stageWidthToUse = stage.stageWidth;
            GameIntro.stageHeightToUse = stage.stageHeight;

            var intro:IntroClassToUse = new IntroClassToUse();
            stage.addChild(intro);
        }

    }
}

IntroClassToUse.as

package
{
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    /**
     * You need to have library symbol linked to this class in .fla with two mcs - 
     * mcFromLibrarySymbol (dragable) and repButton (reapatButton)
     */
    public class IntroClassToUse  extends MovieClip
    {
        var t = 0; //timer ticks
        var fc:uint = 0; //frames counter
        var isDead = 0;
        var mc;
        static var repButton;
        var logicContex:Timer = new Timer(30);

        public function IntroClassToUse() {
            trace("toUse", GameIntro.stageWidthToUse);
            mc = mcFromLibrarySymbol;
            if(!repButton) repButton = repButtonX;
            logicContex.addEventListener(TimerEvent.TIMER, logicInterval);
            logicContex.start();
            init();
        }

        internal function init() {
            trace("init");
            mc.alpha = 1;
            mc.addEventListener(Event.ENTER_FRAME, onFrame);
            mc.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
            mc.x = 0.516 * GameIntro.stageWidthToUse;
            mc.y = 0.75 * GameIntro.stageHeightToUse;
            mc.height = 0.2 * GameIntro.stageHeightToUse;
            mc.width = mc.height / 1.4;
            GameIntro.STAGE.stage.addChildAt(mc, 1);
        }

        internal function onLoose() {
            trace("onLoose");
            mc.removeEventListener(Event.ENTER_FRAME , onFrame);
            mc.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
            GameIntro.STAGE.stage.removeChild(mc);
            mc.alpha = 0;
            isDead = 1;
            repButton.x = 0.127 * GameIntro.stageWidthToUse;
            repButton.y = 0.91 * GameIntro.stageHeightToUse;
            repButton.addEventListener(MouseEvent.CLICK, onReplay);
            repButton.alpha = 1;
        }

        internal function onReplay(e:MouseEvent):void {
            trace("onReplay");
            repButton.removeEventListener(MouseEvent.CLICK, onReplay);
            repButton.alpha = 0;
            stop();
            new IntroClassToUse();
        }

        internal function onMDown(e:MouseEvent):void {
            trace("mouseDow");
            GameIntro.STAGE.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
            GameIntro.STAGE.stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
        }       

        internal function onMMove(e:MouseEvent):void {
            mc.x = e.stageX;
            mc.y = e.stageY;    
        }

        //you loose the game if you release you mc with part of it over rigth stage edge.
        internal function onMUp(e:MouseEvent):void {
            trace("mouseUp");
            GameIntro.STAGE.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
            GameIntro.STAGE.stage.removeEventListener(MouseEvent.MOUSE_UP, onMUp);
            trace("Stage:", GameIntro.STAGE.numChildren);
            if (mc.x + mc.width > GameIntro.STAGE.stageWidth) onLoose();
        }

        internal function onFrame(e:Event):void {
            trace("frames", fc++);
        }

        internal function logicInterval(e:TimerEvent):void {
            if (t++ < 300 || !isDead) return;
            init();
            mc.alpha = 0;
            mc.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
            isDead = 0;
        }
    }

}
Coricoriaceous answered 14/3, 2017 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.