samedi 11 juin 2016

Nested movieclips; changing background frame

Where have all my children gone?

Hope this is a relatively simple answer to a less-than-intelligent question that's a consequence of how I learn things when not doing them for work. In this case I started a game about 3 years ago in AS3 as I was familiar with js at least and had also worked with shockwave back in the day. Anyway, when learning something offline like this I tend to learn just what I need to know to do what I need to do next, and can sometimes get pretty far into one area while missing something obvious and simple because I just haven't crossed that case yet.

We have a playing field and playing pieces. Those playing pieces (sailing ships) you see below are complex objects with dozens of properties and several children including graphics and text fields that change depending on the state of the ship. It's WEGO where each side plots moves, those moves are then executed one ship at a time alternatively between the two sides, then we have gun combat, etc. All that is there and works fine, a few thousand lines of code.

My current problem is that when a player clicks on a ship to select it, I unhide a yellow border to indicate which ship is selected and draw the complex ship detail screen you see top left, but for a long time I've wanted to change the background color of the playing piece as well.

After a long layoff I started working on this again and decided to start there. So I made new counters, added them as keyframes to the already existing symbol/class that contains all of the country default backgrounds, and modified the code. It works fine in that the background is changed to the correct highlighted version, and then goes back to default when deselected.

In the image the currently-selected ship is in the center, USS Constitution, its detail/info screen is also displayed. You can see the problem, all the children are gone on the playing piece. And they don't come back when you go back to the original default background.

At first I thought it was a z order problem but it isn't, I walked the selected ship playing piece background in the z index until they disappeared behind the ocean background, there was just open ocean where the ship playing piece used to be.

My best guess is that maybe the children have to be instanced on each frame of the parent's timeline each time you change the parent's frame but if so I'm not finding reference to or explanation of that. That and that seems really unwieldy way of doing things, I was completely caught off guard by the idea of the children caring what frame its parent is on unless there was coded logic telling it to.

Somehow even though I have thousands of lines of complex dialogs and screens displaying multiple dynamic children I have never changed the base background in any of those cases.

Also tried to google this, but had little luck. I couldn't even figure out a relatively simple question to ask.

I'll be happy to paste code but I don't seem to have a code problem but an understanding problem.

Example-selected ship with highlighted background graphic is in the center

For those who feel the code is important, this is the end of the 1500 line ship-creation function where most of the children get added:

textShipSailSpeed.name = "textShipSailSpeed";
            textShipSailSpeed.width = 20;
            textShipSailSpeed.height = 13;
            textShipSailSpeed.x = 33;
            textShipSailSpeed.y = 14;
            textShipSailSpeed.embedFonts = true;
            textShipSailSpeed.textColor = 0xFFFFFF;
            textShipSailSpeed.rotation -= 90;

            //full sails set
            if ("full" == finalShip.sailState) {

                textShipSailSpeed.text = finalShip.fullSailSpeed;
            }

            //battle sails set, which are reduced sails to improve visibility and reduce sail damage in combat
            else {

                textShipSailSpeed.text = finalShip.battleSailSpeed;
            }

            // textShipBattleSailSpeed and textShipFullSailSpeed no longer used on counters, but still used in Info screens
            var textShipBattleSailSpeed: TextField = new TextField();
            textShipBattleSailSpeed.name = "textShipBattleSailSpeed";
            textShipBattleSailSpeed.text = finalShip.battleSailSpeed;
            textShipBattleSailSpeed.visible = false;

            var textShipFullSailSpeed: TextField = new TextField();
            textShipFullSailSpeed.name = "textShipFullSailSpeed";
            textShipFullSailSpeed.text = finalShip.fullSailSpeed;
            textShipFullSailSpeed.visible = false;

            //create sailState (battle/full) indicator
            var sailStateIndicator: WSIM_Counters_SailtState_Indicator = new WSIM_Counters_SailtState_Indicator();

            //set indicator to correct sailState background graphic
            sailStateIndicator.gotoAndStop("battle");

            if ("full" == finalShip.sailState) {

                sailStateIndicator.gotoAndStop("full");
            }

            finalShip.addChild(sailStateIndicator);

            //add ship and attach text fields
            gridBG1.addChild(finalShip);
            finalShip.addChild(textShipName);
            finalShip.addChild(textShipSailSpeed);
            finalShip.addChild(textShipTurnAllowance);
            finalShip.addChild(textShipBattleSailSpeed);
            finalShip.addChild(textShipFullSailSpeed);
            finalShip.parent.setChildIndex(finalShip, 1);

            //logging
            if (log_shipCreation) {

                trace(finalShip.name + " added added as child of background in createShip()");
            }

            //create background sprite "ship is selected" border
            var border: Sprite = new Sprite();
            border.name = "shipBorder";
            border.graphics.beginFill(0xFFCC00, 1);
            border.graphics.drawRect(-1, -1, 52, 132)
            border.graphics.endFill();
            border.visible = false;

            //create background sprite combat border
            var borderCombat: Sprite = new Sprite();
            borderCombat.name = "borderCombat";
            borderCombat.graphics.beginFill(0xFF0000, 1);
            borderCombat.graphics.drawRect(-1, -1, 52, 132)
            borderCombat.graphics.endFill();
            borderCombat.visible = false;

            //add the borders as children of ship
            finalShip.addChild(border);
            finalShip.addChild(borderCombat);

            //move the borders in z-order to behind ship counter, so they show looking like a border
            border.parent.setChildIndex(border, border.parent.getChildIndex(border) - 5);
            borderCombat.parent.setChildIndex(borderCombat, borderCombat.parent.getChildIndex(borderCombat) - 6);

            //PUSH TO MASTER SHIP ARRAYS
            //finalShip is Side 1, add to master list of ship objects for Side 1
            if (sideList[0] == finalShip.country) { ....

And this is part of the even larger selectShip function, here is where I clear the selected state on all ships on map and then set the current ship's background to currShip.country+"_sel" which is the correct frame label for the "selected" background images.

//clear combat selected state on all ships
            for (var i: int = 0; i < shipListSide1.length; i++) {

                //hide selection border sprite and set select property false
                shipListSide1[i].combatSelected = false;
                var borderChildCombat = shipListSide1[i].getChildByName("borderCombat");
                borderChildCombat.visible = false;

                //show default counter background, build label name
                shipListSide1[i].gotoAndStop(shipListSide1[i].country+"_def");
            }

            for (var i: int = 0; i < shipListSide2.length; i++) {

                //hide selection border sprite and set select property false
                shipListSide2[i].combatSelected = false;

                var borderChildCombat2 = shipListSide2[i].getChildByName("borderCombat");
                borderChildCombat2.visible = false;

                //show default counter background, build label name
                shipListSide2[i].gotoAndStop(shipListSide2[i].country+"_def");
            }

            //check to see if this is selecting a target in gun combat
            if ((false == currShip.side1 && enableCombatSelectSide2) || (currShip.side1 && enableCombatSelectSide1)) {

                combatSelectShip(currShip);
            }

            //we're allowed to select this ship
            if ((enableSelectSide1 && currShip.side1) || (enableSelectSide2 && false == currShip.side1)) {

                //event is from a ship object
                if (currShip is Ship_1) {

                    //remove previous ship info screen
                    if (currShipInfo.parent) {

                        currShipInfo.parent.removeChild(currShipInfo);
                    }


                    //clear selected state on all ships
                    for (var i: int = 0; i < shipListSide1.length; i++) {

                        //hide selection border sprite and set select property false
                        shipListSide1[i].selected = false;

                        var borderChild = shipListSide1[i].getChildByName("shipBorder");
                        borderChild.visible = false;

                        //default graphic already set in clearing combatselect status above
                    }

                    for (var i: int = 0; i < shipListSide2.length; i++) {

                        //hide selection border sprite and set select property false
                        shipListSide2[i].selected = false;

                        var borderChild2 = shipListSide2[i].getChildByName("shipBorder");
                        borderChild2.visible = false;

                        //default graphic already set in clearing combatselect status above
                    }

                    //Change graphic of selected ship to selected, highlighted color
                    currShip.gotoAndStop(currShip.country+"_sel");

                    //set selected state on clicked ship, unhide border
                    currShip.selected = true;
                    borderChild = currShip.getChildByName("shipBorder");
                    borderChild.visible = true;

Ok based on feedback about it being a z-order issue, the below is what I tried to move the missing children back above the playing piece background. If you notice it also has to be a z order issue as the "selected" border, which is a child of the playing piece like the missing ones, that happens to purposely be behind the playing piece graphic, displays correctly when the ship is in the selected state. See the original screenshot, the playing piece in the center that's selected and is missing its children also has a yellow border.

Anyway, below is what I tried. It works in that there are no errors but I really couldn't find these children in the debugger to confirm what happened, and so far I at least appear to have moved them up in the z order to the max before I get an out of range error, and the problem still exists - no ship graphic, ship name, movement allowance, etc.

//Change playing piece background of the selected ship to selected, highlighted color frame
                    currShip.gotoAndStop(currShip.country+"_sel");

                    //trying to move the children of the playing piece back above the playing piece graphic
                    var shipChildrenArray:Array = new Array("textShipName","textShipTurnAllowance","textShipSailSpeed","sailStateIndicator");

                    for each(var childItem:String in shipChildrenArray) {

                        currShip.setChildIndex(currShip.getChildByName(childItem), 3);
                    }

Aucun commentaire:

Enregistrer un commentaire