简体   繁体   中英

How do I unload an external “.swf” file to load another?

I am a student who's working for months on a game and now I've got stuck on a problem. I am new to actionscript 3 but i learn fast.

I can load my menu screen ("startScreen.swf") into my game (firstgame) automatically and everything works fine when I click play or storyScreen or instructionsScreen. But the problem is that I want to return after pressing ESC button. I have tried many code but nothing works exactly how I want.

Example: I click on story and the swf (storyScreen.swf) loads and I can read the story and when I am finished, I want to press ESC to reload my swf (startScreen.swf) and all the functions in it. Like play and instructions.

You can find my code and empty space in the function ( esc ).

I know it is maybe easy to solve but I really don't know how. :(

public class FirstGame extends MovieClip
{

    public var Player:MovieClip

    private var leftKeyIsDown:Boolean;
    private var RightKeyIsDown:Boolean;

    private var aMissileArray:Array;
    private var aEnemyArray:Array;

    public var scoreTxt:TextField;
    public var ammoTxt:TextField;
    public var MenuEnd:EndGameScreen;
    public var menuAgain:EndGameScreen;

    private var MenuStart:mcStartGameScreen;
    private var MenuStory:mcStartGameScreen;
    private var MenuInstructions:mcStartGameScreen;

    private var nScore:Number;
    private var nAmmo:Number;
    private var tEnemyTimer:Timer;


    public function FirstGame() 
    {
        //Create a loader object
        var startLoader:Loader = new Loader();
        //add event listener to listen for the complete event
        startLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, startLoaded);
        //load our loader object
        startLoader.load(new URLRequest("startScreen.swf"));
    }

    public function startLoaded(e:Event):void 
    {
        MenuEnd.hideScreen();
        Player.visible = false;
        scoreTxt.visible = false;
        ammoTxt.visible = false;

        //get a reference to the loaded movieclip
        MenuStart = e.target.content as mcStartGameScreen;
        //listen for start game event
        MenuStart.addEventListener("START_GAME", playGameAgain);
        //add it to the stage
        addChild(MenuStart);

        //get a reference to the loaded movieclip
        MenuStory = e.target.content as mcStartGameScreen;
        //listen for start game event
        MenuStory.addEventListener("SHOW_STORY", storyGameScreen);
        //add it to the stage
        addChild(MenuStory);

        //get a reference to the loaded movieclip
        MenuInstructions = e.target.content as mcStartGameScreen;
        //listen for start game event
        MenuInstructions.addEventListener("SHOW_INSTRUCTIONS", instructionsGameScreen);
        //add it to the stage
        addChild(MenuInstructions);
    }

    private function instructionsGameScreen(e:Event):void 
    {
        var instructionsLoader:Loader = new Loader();
        var url:URLRequest = new URLRequest("instructionsScreen.swf");
        instructionsLoader.load(url);
        addChild(instructionsLoader);

        stage.addEventListener(KeyboardEvent.KEY_UP, esc);
    }

    private function storyGameScreen(e:Event):void 
    {
        var storyLoader:Loader = new Loader();
        var url:URLRequest = new URLRequest("storyScreen.swf");
        storyLoader.load(url);
        addChild(storyLoader);

        stage.addEventListener(KeyboardEvent.KEY_UP, esc);
    }

    private function esc(e:KeyboardEvent):void 
    {
        if (e.keyCode == 27) 
        {
            //fscommand("quit");

            /////////test//////////////////(new URLRequest(stage.loaderInfo.url), "FirstGame.swf");

        }
    }


    private function playGameAgain(e:Event):void 
    {

        //initialize variables
        aMissileArray = new Array();
        aEnemyArray = new Array();
        nScore = 0;
        nAmmo = 20;
        Player.x = 262,95
        Player.y = 323,30

        Player.visible = true;
        scoreTxt.visible = true;
        ammoTxt.visible = true;

        MenuStart.hideScreen();


        MenuEnd.addEventListener("PLAY_AGAIN", playGameAgain);
        MenuEnd.hideScreen();

        updateScoreText();
        updateAmmoText();

        //trace("First Game Loaded");
        stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
        stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);

        stage.addEventListener(Event.ENTER_FRAME, gameLoop)

        //creat an timer object
        tEnemyTimer = new Timer(1000)
        //listen for the timer ticks/intervals
        tEnemyTimer.addEventListener(TimerEvent.TIMER, addEnemy)
        //start our timer
        tEnemyTimer.start();

    }

I believe you should be able to start a new request on the same loader object. Either way, you're dealing with object creation + cleanup. The crux of the solution I'm offering is that you reuse your loaders.

Your current code is somewhat repetitious, so I've modified it slightly to demonstrate how you could simplify the code. Some thoughts while reviewing your code:

  • You're adding the same object to the stage multiple times (ie., MenuStart, MenuStory, MenuInstructions); these are all pointers to the same root swf you loaded (aka, startLoader).
  • You've registered events the stage at multiple locations. Best practice is to place these in your constructor as they are persistent.
  • Because you want to reuse your loaders at a later point, keeping a table with them makes it easier to reference.
  • Any time you find yourself programming the same code in similar ways, it's a good indication that you can simplify with a single function (simply change the arguments).

Give this a try:

public var Player:MovieClip

private var leftKeyIsDown:Boolean;
private var RightKeyIsDown:Boolean;

private var aMissileArray:Array;
private var aEnemyArray:Array;

public var scoreTxt:TextField;
public var ammoTxt:TextField;
public var MenuEnd:EndGameScreen;
public var menuAgain:EndGameScreen;

private var MenuStart:mcStartGameScreen;
private var MenuStory:mcStartGameScreen;
private var MenuInstructions:mcStartGameScreen;

private var nScore:Number;
private var nAmmo:Number;
private var tEnemyTimer:Timer;

private var screens:Object = {
    "SHOW_INSTRUCTIONS":{
        "loader":new Loader(),
        "url":new URLRequest("instructionsScreen.swf")
    },
    "SHOW_STORY":{
        "loader":new Loader(),
        "url":new URLRequest("storyScreen.swf")
    },
    "START_GAME":{
        "loader":new Loader(),
        "url":new URLRequest("startScreen.swf")
    }
}

public function FirstGame() {
    var startLoader:Loader = loadScreen({"type":"START_GAME"});
    //Register our event listeners
    startLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, startLoaded);
    stage.addEventListener(KeyboardEvent.KEY_UP, esc);
    stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
    stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
    stage.addEventListener(Event.ENTER_FRAME, gameLoop)
}

private function loadScreen(e:Object):Loader {
    screens[e.type].loader.load(screens[e.type].url);
    addChild(screens[e.type].loader);
    return screens[e.type].loader;
}

public function startLoaded(e:Event):void {
    //initialize variables
    aMissileArray = new Array();
    aEnemyArray = new Array();
    nScore = 0;
    nAmmo = 20;
    Player.x = 262, 95
    Player.y = 323, 30
    Player.visible = true;
    scoreTxt.visible = true;
    ammoTxt.visible = true;
    MenuEnd.addEventListener("PLAY_AGAIN", playGameAgain);
    MenuEnd.hideScreen();
    updateScoreText();
    updateAmmoText();

    //creat an timer object
    tEnemyTimer = new Timer(1000)
    tEnemyTimer.addEventListener(TimerEvent.TIMER, addEnemy)
    tEnemyTimer.start();

    var swfRoot = screens.START_GAME.loader["content"];
    swfRoot.addEventListener("START_GAME", loadScreen);
    swfRoot.addEventListener("SHOW_STORY", loadScreen);
    swfRoot.addEventListener("SHOW_INSTRUCTIONS", loadScreen);
}

private function esc(e:KeyboardEvent):void {
    if (e.keyCode == 27) {
        //fscommand("quit");

        // Loop through our loaders, and reset them all.
        for each (var entry:Object in screens) {
            entry.loader.unloadAndStop();
            removeChild(entry.loader);
        }

        // Reload the start screen
        var startLoader:Loader = loadScreen({"type":"START_GAME"});
        startLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, startLoaded);
    }
}

The last thing I want to be guilty of is telling you how to run your project, however, I think you may be taking the wrong approach, here.

Instead of setting up the story and the game as separate swf files, what you would probably need to do is set up the story as a MovieClip, and the game as a MovieClip. (Yes, MovieClips can contain other symbols, including other MovieClips.) Then, you'll want to hide/show or add/remove these MovieClips from your stage using code.

If you need to know how to do this, let me give you the age-old admonishment: RTD (Read the Documentation). These are basic tasks that are covered both in the online Adobe Flash documentation, and across numerous tutorials online.

I hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM