A Flash Developer Resource Site

Results 1 to 13 of 13

Thread: CS4 AS2 Problem with gotoAndPlay or onEnterFrame

  1. #1

    CS4 AS2 Problem with gotoAndPlay or onEnterFrame

    See SWF file here: Pacman

    I’m having trouble locating this bug. When the board is complete, the main timeline is supposed to gotoAndPlay another scene. I have the first frame of the scene labeled “Board Done”. This frame also has AS that removes the dynamically created MovieClips. For debugging, I commented out the part that removes the main board container.

    Actionscript Code:
    //BoardContainer.removeMovieClip();
    for(x=0;x<lives;x++)
        this["life"+x].removeMovieClip();
    for(x=0;x<12;x++)
        this["round"+x].removeMovieClip();
    FrameBorder.removeMovieClip();
    Frameback.removeMovieClip();
    Scores.removeMovieClip();

    I don’t know why this would be a problem, but at this point, it was stopping, as though I had used gotoAndStop.


    The board is supposed to end when the last dot is gotten. The checkForDot function does this, and it is called by the Player.onEnterFrame function. When checkForDot finds that there are no more dots, it is supposed to remove the Player.onEnterFrame function, since the player should no longer have control, and move the main timeline to the other scene:


    Actionscript Code:
    _global.checkForDot=function(x:Number,y:Number):Void
    {
        //round pixel coordinates of player to find tile coordinate of dot
        x=Math.floor((x+7.5)/15);
        y=Math.floor((y+7.5)/15);

        if(map[x][y].Dot._currentframe==undefined)//no dot here
            return;
           
        if(map[x][y].Dot._currentframe==2)
            changeEnemies();
        else
            getDot.start(); //dot sound only
       
        map[x][y].Dot.removeMovieClip();
        numDots--;
        score++;
        checkScore(); //for extra life

        if(numDots==0) //no dots left - end round
        {
            round++;
            delete Player.onEnterFrame;
            _level0.gotoAndPlay("Board Done");
            //setTimeout(gotoAndPlay,100,"Board Done");
        }
    }

    By not removing the board container MovieClip, I found that the main timeline was not moving. It must be some other timeline since the code on that frame is executed, but the code running from the main timeline during the game is still running. If it weren’t, new bonuses would not appear and the pause function would not work.

    As you can see, I tried specifying _level0 for the gotoAndPlay, I tried making the function global, and I tried using setTimeout. When I use setTimeout, the code on the other scene never executes.

    Does anyone have any hint of an idea why this happens?

  2. #2
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    You didn't delete _root.onEnterFrame...That would only make a difference if you specified an onEnterFrame for the root, which I am assuming you did.
    Z¡µµ¥ D££

    Soup In A Box

  3. #3
    No, I don’t have an onEnterFrame in the root. The scripts in the root are on frame 34, then frame 35 has a gotoAndPlay(34). I know this is in bad form, which is why I removed the player code from here and put it in Player.onEnterFrame. It was when I did this that the defect started, which is why I suspect onEnterFrame. The only code that remains in the timeline on frame 34 is for starting the enemies, starting bonuses, and pausing.


    Actionscript Code:
    //start enemies

    if(time<=ENEMYSTART[numEnemies][numEnemies-1].t)
    {
        for(i=0;i<numEnemies;i++)
        {
            if(time==ENEMYSTART[numEnemies][i].t)
            {
                Enemy[i].mode=1;
                Enemy[i].gotoAndPlay(6);
            }
        }
    }

    if(bonustimer==200)
    {
        //bonus
        var Bonus:MovieClip;
        Bonus=BoardContainer.attachMovie("Bonuspic","Bonus",DEPTH.bonus,{_xscale:15,_yscale:15});
        Bonus.gotoAndPlay(2);
        Bonus.type.gotoAndStop((round%numBonuses)+1);
    }

    if( Key.isDown(80) && time>unpausetime+15)
    {                       //pause
        for (i=0;i<numEnemies;i++)
            Enemy[i].stop();

        Bonus.stop();
        Bonus.Stop.stop();
        Text.gotoAndStop(2);
        Text._visible=true;
        delete Player.onEnterFrame;
        gotoAndPlay(36);
    }

    time++;
    bonustimer++;

    So what I'm expecting when I have the gotoAndPlay("Board Done") is that this part of the code will stop since the root playhead is no longer here. Somehow it’s staying here while still executing the code in the "Board Done" scene.

  4. #4
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    Can you post the code for Player.onEnterFrame?
    Z¡µµ¥ D££

    Soup In A Box

  5. #5
    Okay, this will take a little more explanation though.

    The map matrix is only used for display and holding the dots. For everything else, the nodes are used. Player.node1 is the node either to the up or to the left of the player. Player.node2 is the node either to the down or to the right of the player. When the player is at a node, Player.node1 equals Player.node2 and Player.atNode equals true.

    If a key is pressed while the player is between nodes, it will only do something immediately if it is for the opposite direction of the player. If it is the same direction, it is ignored. If it is a different direction, is is stored for six frames (constant KEYTIME) and it will be used if the player reaches a node with that direction available in that time.

    NODIR, UP, RIGHT, DOWN, and LEFT are constants with values 0, 1, 2, 3, and 4 respectively. (In retrospect, I should have put positive directions together.)

    Each node has an array toThe, and elements 1 through 4 contain the array index of the node in that direction. If there is no node in that direction, it is -1 (constant WALL). The nodes also have x and y coordinates and inBounds.

    Actionscript Code:
    _global.playerMain=function(Void):Void
    {
        //check for attempted direction change
       
        if(lastkeytime && !(--lastkeytime)) //check for time over for stored keystroke
            lastkey=NODIR;              //remove stored keystroke
       
        if(!Player.atNode)  //key pressed while not at node
        {
            for(i=UP;i<=LEFT;i++)//reverse direction between nodes, or store for later
            {
                if(!Key.isDown(KEY[i]))//if this key's not pressed, skip and check next direction
                    continue;
               
                if(Key.isDown(KEY[oppositeDir(i)]))//if this and opposite key are both pressed, skip
                    continue;
               
                if(Player.dir==oppositeDir(i))//switch direction
                {
                    Player.dir=i;
                    Player.gotoAndStop(i);
                    lastkey=NODIR;
                }
                else if(Player.dir!=i)//save keystroke for later
                {
                    lastkey=i
                    lastkeytime=KEYTIME;
                }
            }
        }
        else    //at node
        {              
            //trace(playernode1+" "+node[playernode1].inBounds);
            for(i=UP;i<=LEFT;i++)  //check for new keystroke
            {
                if( Key.isDown(KEY[i]) && Player.dir!=i && node[Player.node1].toThe[i]!=WALL && !Key.isDown(KEY[oppositeDir(i)]) )
                    lastkey=i;     
            }
       
       
            if(lastkey && node[Player.node1].toThe[lastkey]!=WALL) //change direction if possible
            {
                Player.dir=lastkey;
       
                //recenter player
                Player._x=node[Player.node1].x*TILESIZE;
                Player._y=node[Player.node1].y*TILESIZE;
               
                //set new dest node
                if(Player.dir==UP || Player.dir==LEFT)
                    Player.node1=node[Player.node1].toThe[Player.dir];
                else
                    Player.node2=node[Player.node1].toThe[Player.dir];     
                   
                lastkey=NODIR;
                Player.atNode=false;
                Player.gotoAndStop(Player.dir);
            }
            else//set new dest node if passing through
            {
                if(Player.dir && node[Player.node1].toThe[Player.dir]!=WALL)
                {
                    if(Player.dir==UP || Player.dir==LEFT)
                        Player.node1=node[Player.node1].toThe[Player.dir];
                    else
                        Player.node2=node[Player.node1].toThe[Player.dir];
                   
                    Player.atNode=false;
                }
       
            }
           
        }
           
        //move player
       
        Player._x+=vectorX[Player.dir]*Player.speed;
        Player._y+=vectorY[Player.dir]*Player.speed;

        //Dots
        checkForDot(Player._x,Player._y);
       
        //check enemy collision
        checkEnemyCollision();
       
        //check for Bonus collision
        checkBonusCollision();
       
        //check for new node
       
        if(Player.dir==UP && (Player._y-Player.speed)/TILESIZE < node[Player.node1].y)
        {   Player.node2=Player.node1;  Player.atNode=true;}
        else if(Player.dir==RIGHT && (Player._x+Player.speed)/TILESIZE > node[Player.node2].x)
        {   Player.node1=Player.node2;  Player.atNode=true; }
        else if(Player.dir==DOWN && (Player._y+Player.speed)/TILESIZE > node[Player.node2].y)
        {   Player.node1=Player.node2;  Player.atNode=true; }
        else if(Player.dir==LEFT && (Player._x-Player.speed)/TILESIZE < node[Player.node1].x)
        {   Player.node2=Player.node1;  Player.atNode=true;}
       

       
        if(Player.atNode && Player.dir)
        {
            if(!node[Player.node1].inBounds)//check for out of bounds
            {
                if(node[Player.node1].y==-2)
                {
                    Player.node2=node[Player.node1].toThe[UP];
                    Player.node1=node[Player.node2].toThe[UP];
                    Player._x=node[Player.node2].x*TILESIZE;
                    Player._y=node[Player.node2].y*TILESIZE-Player.speed;
                }
                else if(node[Player.node1].y==maxY+2)
                {
                    Player.node1=node[Player.node2].toThe[DOWN];
                    Player.node2=node[Player.node1].toThe[DOWN];
                    Player._x=node[Player.node1].x*TILESIZE;
                    Player._y=node[Player.node1].y*TILESIZE+Player.speed;
                }
                else if(node[Player.node1].x==-2)
                {
                    Player.node2=node[Player.node1].toThe[LEFT];
                    Player.node1=node[Player.node2].toThe[LEFT];
                    Player._x=node[Player.node2].x*TILESIZE-Player.speed;
                    Player._y=node[Player.node2].y*TILESIZE;
                }
                else if(node[Player.node1].x==maxX+2)
                {
                    Player.node1=node[Player.node2].toThe[RIGHT];
                    Player.node2=node[Player.node1].toThe[RIGHT];
                    Player._x=node[Player.node1].x*TILESIZE+Player.speed;
                    Player._y=node[Player.node1].y*TILESIZE;
                }
                Player.atNode=false;
            }
            else if(node[Player.node1].toThe[Player.dir]==WALL)//check for end of path
            {
                Player.dir=NODIR;
                Player._x=node[Player.node1].x*TILESIZE;//recenter player
                Player._y=node[Player.node1].y*TILESIZE;
            }
        }
    }

  6. #6
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    That is an interesting way of setting it up, but it does make sense.

    What would happen if you moved "checkForDot(Player._x,Player._y);" to the end? I don't think it would make a difference, but it might.
    Z¡µµ¥ D££

    Soup In A Box

  7. #7
    I tried moving checkForDot to the end and didn’t notice a difference.

    Another possible clue is the behavior of the enemies when the player is caught and the board resets. Some enemies will move back to their original position in the base and act as they are supposed to. Some will keep their position from before but move as though in the base. Some will start to move out of the base and get stuck. But it’s all intermittent.

  8. #8
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    So, is the movie actually even going to the "Board Done" scene and then stopping? Or is it just stopping without going to the next scene?
    Z¡µµ¥ D££

    Soup In A Box

  9. #9
    I think that’s the heart of the question. It seems to be doing both.

    It continues to generate bonuses and allows pausing, which is only possible if it continues to alternate between frames 34 and 35 in the main "Game" scene timeline.

    However, it is removing all the MovieClips (except the main board container) and the code for that is only on frame 1 of the "Board Done" scene (and "Game Over").

    The only thing that comes to my mind is something with the nested objects. That’s why I explicitly move a lot of things to _root or made them global. That didn’t make any difference though.

  10. #10
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    Hmm...This seems pretty weird.This definitely isn't a straightforward answer (which always makes it more interesting). Could you possibly post the .fla so I could try a few things?
    Z¡µµ¥ D££

    Soup In A Box

  11. #11
    Did you get my email yesterday?

  12. #12
    var x:Number = 1; x /= 0;
    Join Date
    Dec 2004
    Posts
    549
    Yeah, I got it today, but I forgot you have CS4, and I forgot to mention that I'm using CS3.
    Z¡µµ¥ D££

    Soup In A Box

  13. #13
    Hi, I sent the CS3 version on 7/10. Have you had a chance to look at it?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center