Optymalizacja mojego dynamicznego silnika tła do gry flash 2d w actionscript-3

Edytuj 2: sądząc po braku odpowiedzi zaczynam się zastanawiać, czy mój problem jest wystarczająco jasny. Proszę mi powiedzieć, czy muszę opracować więcej.

Uwaga: zobacz na dole aktualizację kodu!

Krótkie wprowadzenie: Piszę dwuwymiarową grę flashową w Actionscript. Wszechświat jest nieskończenie duży, z powodu tej cechy tło musi być renderowane dynamicznie, a obiekty tła (chmury gazu, gwiazdy itp.) Muszą być rozmieszczone losowo.

Stworzyłem klasę o nazwie BackgroundEngine i działa ona bardzo dobrze, problem polega jednak na wydajności renderowania. Tak to działa:

Podczas uruchamiania wokół odtwarzacza tworzone są 4 kontenery tła (każdy o wielkości sceny). Górny lewy, prawy górny, lewy dolny i prawy dolny. Wszystkie kwadraty tła są dodawane do głównego kontenera, co ułatwia przemieszczanie tła. Teraz są 2 funkcje odpytywania:

1) „garbage poller”: szuka kontenerów tła, które są 2 razy większe od szerokości lub wysokości sceny, odpowiednio od współrzędnych X lub Y gracza. Jeśli tak, usunie ten kwadrat tła i zezwoli na zbieranie śmieci.

2) „odpytywanie renderujące”: sprawdza, czy obecnie jest tło na wszystkich stronach odtwarzacza (x - stageWidth, x + stageWidth, y - stageHeight, y + stageHeight). Jeśli nie, narysuje nowy kwadrat tła w odpowiednim miejscu.

Wszystkie kwadraty tła są tworzone z następującą funkcją (te tworzone dynamicznie i cztery podczas uruchamiania):

<<< usunięto stary kod, zobacz na dole, aby uzyskać zaktualizowane pełne źródło >>>

Wszystkie random, które tam widzisz, zapewniają, że środowisko wygląda wyjątkowo na każdym placu. To naprawdę działa świetnie, wszechświat wygląda całkiem niesamowicie.

Następujące zasoby są używane jako obiekty w tle:

1) Proste gwiazdy:http://www.feedpostal.com/client/assets/background/1.png (prawdopodobnie nie będziesz w stanie zobaczyć tego w przeglądarce na białym tle).

2) Jasne gwiazdy:http://www.feedpostal.com/client/assets/background/2.png

3) Białe chmury gazu:http://www.feedpostal.com/client/assets/background/3.png

4) Czerwone chmury gazu:http://www.feedpostal.com/client/assets/background/4.png

Ważne notatki:

1) Wszystkie zasoby są buforowane, więc nie muszą być ponownie pobierane przez cały czas. Są one pobierane tylko raz.

2) Obrazy nie obracają się ani nie są skalowane po ich utworzeniu, więc włączyłem cacheAsBitmap dla wszystkich obiektów, kontenerów i kontenera głównego.

3) Musiałem używać formatów PNG w Photoshopie, ponieważ GIF nie wydawał się bardzo dobrze renderowany w pamięci flash, gdy był używany z przezroczystością.

Problem polega na tym, że kiedy latam wokół, renderowanie tła wymaga zbyt dużej wydajności: klient rozpoczyna „opóźnianie” (mądry FPS). Z tego powodu muszę zoptymalizować silnik w tle, aby był renderowany znacznie szybciej. Czy możecie pomóc mi tutaj?

Aktualizacja 1: To jest to, co mam do tej pory po jednej odpowiedzi, którą otrzymałem.

BackgroundEngine.as

package com.tommedema.background
{
    import br.com.stimuli.loading.BulkLoader;

    import com.tommedema.utils.Settings;
    import com.tommedema.utils.UtilLib;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;

    public final class BackgroundEngine extends Sprite
    {
        private static var isLoaded:Boolean = false;
        private static var bulkLoader:BulkLoader = BulkLoader.getLoader("main");
        private static var masterContainer:Sprite;
        private static var containers:Array = [];
        private static var stageWidth:uint;
        private static var stageHeight:uint;
        private static var assets:Array;

        //moves the background's X coord
        public static function moveX(amount:Number):void
        {
            if (masterContainer)
            {
                masterContainer.x += amount;
                collectGarbage();
                drawNextContainer();
            }
        }

        //moves the background's Y coord
        public static function moveY(amount:Number):void
        {
            if (masterContainer)
            {
                masterContainer.y += amount;
                collectGarbage();
                drawNextContainer();
            }
        }

        //returns whether the background engine has been loaded already
        public static function loaded():Boolean
        {
            return isLoaded;
        }

        //loads the background engine
        public final function load():void
        {
            //set stage width and height
            stageWidth = stage.stageWidth;
            stageHeight = stage.stageHeight;

            //retreive all background assets
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/1.png", {id: "background/1.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/2.png", {id: "background/2.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/3.png", {id: "background/3.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/4.png", {id: "background/4.png"});
            bulkLoader.addEventListener(BulkLoader.COMPLETE, assetsComplete);
            bulkLoader.start();

            //set isLoaded to true
            isLoaded = true;
        }

        //poller function for drawing next background squares
        private static function drawNextContainer():void
        {
            var stageCenterX:Number = stageWidth / 2;
            var stageCenterY:Number = stageHeight / 2;
            var curContainer:Bitmap = hasBackground(stageCenterX, stageCenterY);
            if (curContainer)
            {
                //top left
                if (!hasBackground(stageCenterX - stageWidth, stageCenterY - stageHeight)) drawNewSquare(curContainer.x - stageWidth, curContainer.y - stageHeight);
                //top
                if (!hasBackground(stageCenterX, stageCenterY - stageHeight)) drawNewSquare(curContainer.x, curContainer.y - stageHeight);
                //top right
                if (!hasBackground(stageCenterX + stageWidth, stageCenterY - stageHeight)) drawNewSquare(curContainer.x + stageWidth, curContainer.y - stageHeight);
                //center left
                if (!hasBackground(stageCenterX - stageWidth, stageCenterY)) drawNewSquare(curContainer.x - stageWidth, curContainer.y);
                //center right
                if (!hasBackground(stageCenterX + stageWidth, stageCenterY)) drawNewSquare(curContainer.x + stageWidth, curContainer.y);
                //bottom left
                if (!hasBackground(stageCenterX - stageWidth, stageCenterY + stageHeight)) drawNewSquare(curContainer.x - stageWidth, curContainer.y + stageHeight);
                //bottom
                if (!hasBackground(stageCenterX, stageCenterY + stageHeight)) drawNewSquare(curContainer.x, curContainer.y + stageHeight);
                //bottom right
                if (!hasBackground(stageCenterX + stageWidth, stageCenterY + stageHeight)) drawNewSquare(curContainer.x + stageWidth, curContainer.y + stageHeight);
            }
        }

        //draws the next square and adds it to the master container
        private static function drawNewSquare(x:Number, y:Number):void
        {
            containers.push(genSquareBg());
            var cIndex:uint = containers.length - 1;
            containers[cIndex].x = x;
            containers[cIndex].y = y;
            masterContainer.addChild(containers[cIndex]);
        }

        //returns whether the given location has a background and if so returns the corresponding square
        private static function hasBackground(x:Number, y:Number):Bitmap
        {
            var stageX:Number;
            var stageY:Number;
            for(var i:uint = 0; i < containers.length; i++)
            {
                stageX = masterContainer.x + containers[i].x;
                stageY = masterContainer.y + containers[i].y;
                if ((containers[i]) && (stageX < x) && (stageX + stageWidth > x) && (stageY < y) && (stageY + stageHeight > y)) return containers[i];
            }
            return null;
        }

        //polling function for old background squares garbage collection
        private static function collectGarbage():void
        {
            var stageX:Number;
            var stageY:Number;

            for(var i:uint = 0; i < containers.length; i++)
            {
                if (containers[i])
                {
                    stageX = masterContainer.x + containers[i].x;
                    stageY = masterContainer.y + containers[i].y;
                    if ((stageX < -stageWidth * 1.5) || (stageX > stageWidth * 2.5) || (stageY < -stageHeight * 1.5) || (stageY > stageHeight * 2.5))
                    {
                        containers[i].parent.removeChild(containers[i]);
                        containers.splice(i, 1);
                    }
                }
            }
        }

        //dispatched when all assets have finished downloading
        private final function assetsComplete(event:Event):void
        {
            assets = [];
            assets.push(bulkLoader.getBitmap("background/1.png")); //star simple
            assets.push(bulkLoader.getBitmap("background/2.png")); //star bright
            assets.push(bulkLoader.getBitmap("background/3.png")); //cloud white
            assets.push(bulkLoader.getBitmap("background/4.png")); //cloud red
            init();
        }

        //initializes startup background containers
        private final function init():void
        {
            masterContainer = new Sprite(); //create master container

            //generate default background containers
            containers.push(genSquareBg()); //top left
            containers[0].x = 0;
            containers[0].y = 0;
            containers.push(genSquareBg()); //top
            containers[1].x = stageWidth;
            containers[1].y = 0;
            containers.push(genSquareBg()); //top right
            containers[2].x = stageWidth * 2;
            containers[2].y = 0;
            containers.push(genSquareBg()); //center left
            containers[3].x = 0;
            containers[3].y = stageHeight;
            containers.push(genSquareBg()); //center
            containers[4].x = stageWidth;
            containers[4].y = stageHeight;
            containers.push(genSquareBg()); //center right
            containers[5].x = stageWidth * 2;
            containers[5].y = stageHeight;
            containers.push(genSquareBg()); //bottom left
            containers[6].x = 0;
            containers[6].y = stageHeight * 2;
            containers.push(genSquareBg()); //bottom
            containers[7].x = stageWidth;
            containers[7].y = stageHeight * 2;
            containers.push(genSquareBg()); //bottom right
            containers[8].x = stageWidth * 2;
            containers[8].y = stageHeight * 2;

            //add the new containers to the master container
            for (var i:uint = 0; i <= containers.length - 1; i++)
            {
                masterContainer.addChild(containers[i]);    
            }

            //display the master container
            masterContainer.x = 0 - stageWidth;
            masterContainer.y = 0 - stageHeight;
            masterContainer.cacheAsBitmap = true;
            addChild(masterContainer);
        }

        //duplicates a bitmap display object
        private static function dupeBitmap(source:Bitmap):Bitmap {
            var data:BitmapData = source.bitmapData;
            var bitmap:Bitmap = new Bitmap(data);
            return bitmap;
        }

        //draws a simple star
    private static function drawStar(x:Number, y:Number, width:uint, height:uint):Sprite
    {
        var creation:Sprite = new Sprite();
        creation.graphics.lineStyle(1, 0xFFFFFF);
        creation.graphics.beginFill(0xFFFFFF);
        creation.graphics.drawRect(x, y, width, height);
        return creation;
    }

    //generates a background square
    private static function genSquareBg():Bitmap
    {
        //set 1% margin
        var width:Number = stageWidth * 0.99;
        var height:Number = stageHeight * 0.99;
        var startX:Number = 0 + stageWidth / 100;
        var startY:Number = 0 + stageHeight / 100;

        var scale:Number;
        var drawAmount:uint;
        var tmpBitmap:Bitmap;
        var tmpSprite:Sprite;
        var i:uint;

        //create container
        var container:Sprite = new Sprite();

        //draw simple stars
        drawAmount = UtilLib.getRandomInt(100, 250);
        for(i = 1; i <= drawAmount; i++)
        {
            tmpSprite = drawStar(0, 0, 1, 1);
            tmpSprite.x = UtilLib.getRandomInt(0, stageWidth);
            tmpSprite.y = UtilLib.getRandomInt(0, stageHeight);
            tmpSprite.alpha = UtilLib.getRandomInt(3, 10) / 10;
            scale = UtilLib.getRandomInt(2, 10) / 10;
            tmpSprite.scaleX = tmpSprite.scaleY = scale;
            container.addChild(tmpSprite);
        }

        //draw bright stars
        if (Math.random() >= 0.8) drawAmount = UtilLib.getRandomInt(1, 2);
        else drawAmount = 0;
        for(i = 1; i <= drawAmount; i++)
        {
            tmpBitmap = dupeBitmap(assets[1]);
            tmpBitmap.alpha = UtilLib.getRandomInt(3, 7) / 10;
            tmpBitmap.rotation = UtilLib.getRandomInt(0, 360);
            scale = UtilLib.getRandomInt(3, 10) / 10;
            tmpBitmap.scaleX = scale; tmpBitmap.scaleY = scale;
            tmpBitmap.x = UtilLib.getRandomInt(startX + tmpBitmap.width, width - tmpBitmap.width);
            tmpBitmap.y = UtilLib.getRandomInt(startY + tmpBitmap.height, height - tmpBitmap.height);
            container.addChild(tmpBitmap);
        }

        //draw white clouds
        drawAmount = UtilLib.getRandomInt(1, 4);
        for(i = 1; i <= drawAmount; i++)
        {
            tmpBitmap = dupeBitmap(assets[2]);
            tmpBitmap.alpha = UtilLib.getRandomInt(1, 10) / 10;
            scale = UtilLib.getRandomInt(15, 30);
            tmpBitmap.scaleX = scale / 10;
            tmpBitmap.scaleY = UtilLib.getRandomInt(scale / 2, scale) / 10;
            tmpBitmap.x = UtilLib.getRandomInt(startX, width - tmpBitmap.width);
            tmpBitmap.y = UtilLib.getRandomInt(startY, height - tmpBitmap.height);
            container.addChild(tmpBitmap);
        }

        //draw red clouds
        drawAmount = UtilLib.getRandomInt(0, 1);
        for(i = 1; i <= drawAmount; i++)
        {
            tmpBitmap = dupeBitmap(assets[3]);
            tmpBitmap.alpha = UtilLib.getRandomInt(2, 6) / 10;
            scale = UtilLib.getRandomInt(5, 30) / 10;
            tmpBitmap.scaleX = scale; tmpBitmap.scaleY = scale;
            tmpBitmap.x = UtilLib.getRandomInt(startX, width - tmpBitmap.width);
            tmpBitmap.y = UtilLib.getRandomInt(startY, height - tmpBitmap.height);
            container.addChild(tmpBitmap);
        }

        //convert all layers to a single bitmap layer and return
        var bitmapData:BitmapData = new BitmapData(stageWidth, stageHeight, true, 0x000000);
        bitmapData.draw(container);
        container = null;
        var bitmapContainer:Bitmap = new Bitmap(bitmapData);
        bitmapContainer.cacheAsBitmap = true;
        return bitmapContainer;
    }
    }
}

Gdy gracz się porusza, metody ruchu X i ruchu Y są wywoływane z odwrotnym kierunkiem gracza. Spowoduje to również wywołanie metod collectGarbage i drawNextContainer.

Problem z tą konfiguracją polega na tym, że przez cały czas jest aktywnych co najmniej 9 kontenerów. Górny lewy, górny, górny prawy, środkowy lewy, środkowy, środkowy prawy, dolny lewy, dolny i dolny prawy. To wymaga dużej wydajności.

Edytuj: Zastanawiam się również, czy powinienem używać cacheAsBitmap? Jeśli tak, na jakich obrazach? Na pojemnikach i pojemniku głównym lub tylko na jednym z nich? Kiedy włączam go dla wszystkich obrazów (nawet tymczasowych obiektów sprite), w rzeczywistości jest bardziej opóźniony.

Aktualizacja 2:

Ta wersja używa kwadratów, które są dwa razy większe niż scena. Jednocześnie należy ładować tylko jeden lub dwa kwadraty. Jest lepiej, ale wciąż zauważam uderzenie wydajności podczas ruchu. Sprawia, że ​​klient zamarza na bardzo krótką chwilę. Masz pomysł, jak go zoptymalizować?

BackgroundEngine2.as

package com.tommedema.background
{
    import br.com.stimuli.loading.BulkLoader;

    import com.tommedema.utils.Settings;
    import com.tommedema.utils.UtilLib;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;

    public final class BackgroundEngine2 extends Sprite
    {
        //general
        private static var isLoaded:Boolean = false;        
        private static var bulkLoader:BulkLoader = BulkLoader.getLoader("main");
        private static var assets:Array;

        //objects
        private static var masterContainer:Sprite;
        private static var containers:Array = [];

        //stage
        private static var stageWidth:uint;
        private static var stageHeight:uint;
        private static var stageCenterX:Number;
        private static var stageCenterY:Number;

        //moves the background's X coord
        public static function moveX(amount:Number):void
        {
            if (!masterContainer) return;
            masterContainer.x += amount;
            collectGarbage();
            drawNextContainer();
        }

        //moves the background's Y coord
        public static function moveY(amount:Number):void
        {
            if (!masterContainer) return;
            masterContainer.y += amount;
            collectGarbage();
            drawNextContainer();
        }

        //returns whether the background engine has been loaded already
        public static function loaded():Boolean
        {
            return isLoaded;
        }

        //loads the background engine
        public final function load():void
        {
            //set stage width, height and center
            stageWidth = stage.stageWidth;
            stageHeight = stage.stageHeight;
            stageCenterX = stageWidth / 2;
            stageCenterY = stageHeight / 2;

            //retreive background assets
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/1.png", {id: "background/1.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/2.png", {id: "background/2.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/3.png", {id: "background/3.png"});
            bulkLoader.add(Settings.ASSETS_PRE_URL + "background/4.png", {id: "background/4.png"});
            bulkLoader.addEventListener(BulkLoader.COMPLETE, assetsComplete);
            bulkLoader.start();

            //set isLoaded to true
            isLoaded = true;
        }

        //poller function for drawing next background squares
        private static function drawNextContainer():void
        {
            var curContainer:Bitmap = hasBackground(stageCenterX, stageCenterY);
            if (curContainer)
            {
                if (!hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY - stageHeight * 0.75)) //top left
                    drawNewSquare(curContainer.x - curContainer.width, curContainer.y - curContainer.height);
                if (!hasBackground(stageCenterX, stageCenterY - stageHeight * 0.75)) //top
                    drawNewSquare(curContainer.x, curContainer.y - curContainer.height);
                if (!hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY - stageHeight * 0.75)) //top right
                    drawNewSquare(curContainer.x + curContainer.width, curContainer.y - curContainer.height);
                if (!hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY)) //center left
                    drawNewSquare(curContainer.x - curContainer.width, curContainer.y);
                if (!hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY)) //center right
                    drawNewSquare(curContainer.x + curContainer.width, curContainer.y);
                if (!hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY + stageHeight * 0.75)) //bottom left
                    drawNewSquare(curContainer.x - curContainer.width, curContainer.y + curContainer.height);
                if (!hasBackground(stageCenterX, stageCenterY + stageHeight * 0.75)) //bottom center
                    drawNewSquare(curContainer.x, curContainer.y + curContainer.height);
                if (!hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY + stageHeight * 0.75)) //bottom right
                    drawNewSquare(curContainer.x + curContainer.width, curContainer.y + curContainer.height);
            }
        }

        //draws the next square and adds it to the master container
        private static function drawNewSquare(x:Number, y:Number):void
        {
            containers.push(genSquareBg());
            var cIndex:uint = containers.length - 1;
            containers[cIndex].x = x;
            containers[cIndex].y = y;
            masterContainer.addChild(containers[cIndex]);
        }

        //returns whether the given location has a background and if so returns the corresponding square
        private static function hasBackground(x:Number, y:Number):Bitmap
        {
            var stageX:Number;
            var stageY:Number;
            for(var i:uint = 0; i < containers.length; i++)
            {
                stageX = masterContainer.x + containers[i].x;
                stageY = masterContainer.y + containers[i].y;
                if ((containers[i]) && (stageX < x) && (stageX + containers[i].width > x) && (stageY < y) && (stageY + containers[i].height > y)) return containers[i];
            }
            return null;
        }

        //polling function for old background squares garbage collection
        private static function collectGarbage():void
        {
            var stageX:Number;
            var stageY:Number;
            for(var i:uint = 0; i < containers.length; i++)
            {
                if ((containers[i]) && (!isRequiredContainer(containers[i])))
                {
                    masterContainer.removeChild(containers[i]);
                    containers.splice(i, 1);
                }
            }
        }

        //returns whether the given container is required for display
        private static function isRequiredContainer(container:Bitmap):Boolean
        {
            if (hasBackground(stageCenterX, stageCenterY) == container) //center
                return true;
            if (hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY - stageHeight * 0.75) == container) //top left
                return true;
            if (hasBackground(stageCenterX, stageCenterY - stageHeight * 0.75) == container) //top
                return true;
            if (hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY - stageHeight * 0.75) == container) //top right
                return true;
            if (hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY) == container) //center left
                return true;
            if (hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY) == container) //center right
                return true;
            if (hasBackground(stageCenterX - stageWidth * 0.75, stageCenterY + stageHeight * 0.75) == container) //bottom left
                return true;
            if (hasBackground(stageCenterX, stageCenterY + stageHeight * 0.75) == container) //bottom center
                return true;
            if (hasBackground(stageCenterX + stageWidth * 0.75, stageCenterY + stageHeight * 0.75) == container) //bottom right
                return true;
            return false;
        }

        //dispatched when all assets have finished downloading
        private final function assetsComplete(event:Event):void
        {
            assets = [];
            assets.push(bulkLoader.getBitmap("background/1.png")); //star simple
            assets.push(bulkLoader.getBitmap("background/2.png")); //star bright
            assets.push(bulkLoader.getBitmap("background/3.png")); //cloud white
            assets.push(bulkLoader.getBitmap("background/4.png")); //cloud red
            init();
        }

        //initializes startup background containers
        private final function init():void
        {
            masterContainer = new Sprite(); //create master container

            //generate default background container
            containers.push(genSquareBg()); //top left
            containers[0].x = 0;
            containers[0].y = 0;
            masterContainer.addChild(containers[0]);

            //display the master container
            masterContainer.x = -(stageWidth / 2);
            masterContainer.y = -(stageHeight / 2);
            masterContainer.cacheAsBitmap = true;
            addChild(masterContainer);
        }

        //duplicates a bitmap display object
        private static function dupeBitmap(source:Bitmap):Bitmap {
            var data:BitmapData = source.bitmapData;
            var bitmap:Bitmap = new Bitmap(data);
            return bitmap;
        }

        //draws a simple star
        private static function drawStar(x:Number, y:Number, width:uint, height:uint):Sprite
        {
            var creation:Sprite = new Sprite();
            creation.graphics.lineStyle(1, 0xFFFFFF);
            creation.graphics.beginFill(0xFFFFFF);
            creation.graphics.drawRect(x, y, width, height);
            return creation;
        }

        //generates a background square
        private static function genSquareBg():Bitmap
        {
            var width:Number = stageWidth * 2;
            var height:Number = stageHeight * 2;
            var startX:Number = 0;
            var startY:Number = 0;

            var scale:Number;
            var drawAmount:uint;
            var tmpBitmap:Bitmap;
            var tmpSprite:Sprite;
            var i:uint;

            //create container
            var container:Sprite = new Sprite();

            //draw simple stars
            drawAmount = UtilLib.getRandomInt(100, 250);
            for(i = 1; i <= drawAmount; i++)
            {
                tmpSprite = drawStar(0, 0, 1, 1);
                tmpSprite.x = UtilLib.getRandomInt(startX, width);
                tmpSprite.y = UtilLib.getRandomInt(startY, height);
                tmpSprite.alpha = UtilLib.getRandomInt(3, 10) / 10;
                scale = UtilLib.getRandomInt(5, 15) / 10;
                tmpSprite.scaleX = tmpSprite.scaleY = scale;
                container.addChild(tmpSprite);
            }

            //draw bright stars
            drawAmount = UtilLib.getRandomInt(1, 2);
            for(i = 1; i <= drawAmount; i++)
            {
                tmpBitmap = dupeBitmap(assets[1]);
                tmpBitmap.alpha = UtilLib.getRandomInt(3, 7) / 10;
                tmpBitmap.rotation = UtilLib.getRandomInt(0, 360);
                scale = UtilLib.getRandomInt(3, 10) / 10;
                tmpBitmap.scaleX = scale; tmpBitmap.scaleY = scale;
                tmpBitmap.x = UtilLib.getRandomInt(startX + tmpBitmap.width, width - tmpBitmap.width);
                tmpBitmap.y = UtilLib.getRandomInt(startY + tmpBitmap.height, height - tmpBitmap.height);
                container.addChild(tmpBitmap);
            }

            //draw white clouds
            drawAmount = UtilLib.getRandomInt(2, 4);
            for(i = 1; i <= drawAmount; i++)
            {
                tmpBitmap = dupeBitmap(assets[2]);
                tmpBitmap.alpha = UtilLib.getRandomInt(1, 10) / 10;
                scale = UtilLib.getRandomInt(15, 40);
                tmpBitmap.scaleX = scale / 10;
                tmpBitmap.scaleY = UtilLib.getRandomInt(scale / 2, scale * 2) / 10;
                tmpBitmap.x = UtilLib.getRandomInt(startX, width - tmpBitmap.width);
                tmpBitmap.y = UtilLib.getRandomInt(startY, height - tmpBitmap.height);
                container.addChild(tmpBitmap);
            }

            //draw red clouds
            drawAmount = UtilLib.getRandomInt(0, 2);
            for(i = 1; i <= drawAmount; i++)
            {
                tmpBitmap = dupeBitmap(assets[3]);
                tmpBitmap.alpha = UtilLib.getRandomInt(2, 6) / 10;
                scale = UtilLib.getRandomInt(5, 40) / 10;
                tmpBitmap.scaleX = scale; tmpBitmap.scaleY = scale;
                tmpBitmap.x = UtilLib.getRandomInt(startX, width - tmpBitmap.width);
                tmpBitmap.y = UtilLib.getRandomInt(startY, height - tmpBitmap.height);
                container.addChild(tmpBitmap);
            }

            //convert all layers to a single bitmap layer and return
            var bitmapData:BitmapData = new BitmapData(width, height, true, 0x000000);
            bitmapData.draw(container);
            container = null;
            var bitmapContainer:Bitmap = new Bitmap(bitmapData);
            //bitmapContainer.cacheAsBitmap = true;
            return bitmapContainer;
        }
    }
}

questionAnswers(6)

yourAnswerToTheQuestion