Loading huge content

Hello !

I have one android ported game and one screen that when I try to open with the screenManager need up to 7-10 seconds in order to render the content is there a way to load the content when the game start with a splash screen and loading bar ?

Or in other words how to load many resources in the monogame works without losing gameplay ?

Not on Android but I load everything in the LoadContent and put up a splash screen in the Initialise call. Don’t see why you couldn’t re-draw during the LoadContent to provide a loading bar.

Can you provide a simple demo ?

maybe this could help you

I’ve found threaded loading to work well for me: I load just the bare essentials needed for my splash screen/loading bar (normally my studio logo, a spinner image and a single pixel I use for drawing lines & rectangles) in the normal way, then spin up a new thread with a list of files I want to load.

My main thread then ticks away, firing Update and Draw calls as normal - I’ll have the spinner rotating on this thread, and the progress bar displaying dependent on how many of my files have loaded out of the total count.

Once the loader thread has completed, it rejoins the main thread, and the game moves on to the title screen.

Hope this helps - let me know if you need any sample code.

How to show this splash for x seconds or while the othe screen is still oading resources ?

Demo would be nice,thanks :slight_smile:

Have a look at my game “Bopscotch” (on Google Play) - this will show you it in action.

It would take me a while to pull a minimum version of the code out of the class library I have built up, but basically, I have an “AssetLoaderScene” class in my game state management that inherits from DrawableGameComponent. The Update method starts the loading thread if it has not already been started, and then switches to the next game scene once loading is complete. Here’s an exerpt from the code:

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            if (CurrentState == Status.Active)
            {
                if (string.IsNullOrEmpty(_assetListFileToLoad)) { Deactivate(); }
                else if (ReadyToLoad) { StartThreadedAssetLoad(); }
                else if (LoadCompleted) { CompleteThreadedAssetLoad(); }
            }
        }

        private void StartThreadedAssetLoad()
        {
            \_assetsForThreadedLoad = FileManager.LoadXMLContentFile(_assetListFileToLoad);

            CalculateTotalAssetCount();

            ThreadStart threadStarter = new ThreadStart(ThreadedAssetLoader);
            _loader = new Thread(threadStarter);
            _loader.Start();
        }

        private void ThreadedAssetLoader()
        {
            // Spin through the attribute list and load based on type
            foreach (XElement at in _assetsForThreadedLoad.Element("assets").Elements())
            {
                // Expected XML structure is "assets" - "[assettype]s" - "[asset]"
                foreach (XElement asset in at.Elements())
                {
                    switch (at.Name.ToString())
                    {
                        case "textures":
                            TextureManager.AddTexture(asset.Attribute("name").Value, Game.Content.Load<Texture2D>(asset.Attribute("file").Value));
                            break;
                        case "music":
                            MusicManager.AddTune(asset.Attribute("name").Value, Game.Content.Load<Song>(asset.Attribute("file").Value));
                            break;
                        case "sound-effects":
                            if (asset.Attribute("use-instance") != null)
                            {
                                SoundEffectManager.AddEffect(
                                    asset.Attribute("name").Value,
                                    Game.Content.Load<SoundEffect>(asset.Attribute("file").Value),
                                    (bool)asset.Attribute("use-instance"));
                            }
                            else
                            {
                                SoundEffectManager.AddEffect(
                                    asset.Attribute("name").Value,
                                    Game.Content.Load<SoundEffect>(asset.Attribute("file").Value),
                                    false);
                            }
                            break;
                        case "custom":
                            LoadCustomContent(asset);
                            break;
                    }

                    _loadedAssetCount++;
                }
            }
        }

        private void CompleteThreadedAssetLoad()
        {
            if (_loader != null)
            {
                _loader.Join();
                _loader = null;
            }

            Deactivate();
        }
1 Like

FWIW this is my Initialise function

        protected override void Initialize()
    {
        title = this.Window.Title;
        this.Window.Title = "Loading...";
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        //Splash screen
        Texture2D splashScreen = ResourceCostumes.GetSplashTexture(GraphicsDevice);
        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, screenScale);
        spriteBatch.Draw(splashScreen, new Vector2(0, 0), Microsoft.Xna.Framework.Color.White);
        spriteBatch.End();
        GraphicsDevice.Present();
        // Initialise Stage and scheduler
        Stage = ProcdInit.CreateStage();
        scheduler = new Scheduler(Stage, ProcdInit.CreateExtensions());
        Stage.Initialise(procdGraphicsDX);
        scheduler.InitialiseScheduler();
        base.Initialize();
    }

That is the right idea… but there is little benefit to using Thread. Instead you can use Task:

        static public bool _loadingDone;

        void LoadContent()
        {
            var loading = Task.Factory.StartNew(() =>
            {
                  // Load all your content here.
                  // NOTE: Be sure to catch any exceptions in here and handle them.
                  
                  _loadingDone = true;
            });
        }

Then just let your update/draw keep showing your splash until _loadingDone is true.

My recommendation would be to use another activity that displays the splash screen and then launch you game activity from that.

Can you show me a demo with several screens ?

I did this and what did this implementation for me was that I was able to show loading screen while the resources load fully,but I am thrilled that a project with 548files need time at all to load with today technology that should happend for a seconds maximum,some of the phones characteristics are better then most of the laptop out there in the market.

Maybe the best approach is to understand how many images I am using for the scene and just split them into action BATTLING,IDLE and before each iteratation load to dispose the previous set of images from memory and so on.

If I am using ExEn will I experience any improvement ?

My pictures resolution now is full hd or 1920x1080 is that just alot and I need to rescale it to 1024x768 will that improve the process and implement a scale matrix,how do you optimize your games I am seeing in the monogame game review games like bastion and 3D simulators they are more heavy than the application I am making for sure then why my is so slow,are there any good practises when porting windows xna -> mobile xna(android,ios) or the android is just slow event with android 5.0 and ART running with it ?

can you give me skype or some IM to show you my project in order to tell me any ideas if you have time ?