Working with loading background and progress bar.

You would need to write your code in such a way that the scene builder runs, then stops, then runs, then stops, otherwise as @nick_sherman points out, the loading scene will block any other code, including your ‘progress bar’.

Three ways come to mind:

  • enterFrame driven loader where only a small amount of work is done per frame.
  • timer based (same as above)
  • co-routines - same as above.

I prefer the enterFrame concept and have used it before.

Or you could just use a loading spinner that you fade in at the starting point, and out again when loading is done and just before displaying the newly loaded scene.

Its pretty standard behaviour out there so I doubt users will dismiss that in favour of an old-fashioned loading progress bar.

I think @anaqim is refering to: https://docs.coronalabs.com/api/library/native/setActivityIndicator.html

Hey, I didnt know that one existed so made my own but yes, thats the concept  :slight_smile:

EDIT - And after testing it and reading the tutorials, useless stuff!

On Android it has a solid white background without any options to change it or make it transparent, being a native object.

Make your own with a full screen see through square that catches tap and touch events, and you get the same functionality, yet customizable to your own needs.

Hi again.  

In my experience, the native indicator’s progress is also blocked by the long scene load.  (May work better on devices; Not tested.)

This video demonstrates:

  1. The problem loading a scene that takes a long time to build. - Scene ‘hangs’ for a long time while it builds.
  2. The blocking effect on on the native indicator - Indicator is stuck while loading occurs.
  3. The split loader I identified (enterFrame variant) - Looks and works great.

https://www.youtube.com/watch?v=CYvis_ir9W8&feature=youtu.be

This is the code for the app in the video:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/03/longSceneLoads.zip

Warning: This demo uses SSK to draw buttons, images, rectangles, etc.  That said, the premise of this code is very straight-forward. 

Just take it slowly and I think you’ll see what I did

Tip: Creating your own activity indicator with display objects will NOT work unless you break up the scene loading like I did.  

Corona is single-threaded, so once the scene starts to load, any timer or enterframe code used to update your activity indicator will be blocked.

UPDATE:  This is not a composer.* limitation.  It is true in every case.  For example if you do this:

create spinner object
2.
add enteFrame listener or timer to ‘spin it’
3.
run a function that takes 5 seconds to complete

(also true if the spinner is a animated sprite; it will not animate in step #3)

The spinner will not spin during the time step #3 is executing.  Why?  Corona is single-threaded and the enterFrame handler will not be called while step #3 is running.

FYI - This is where game lag come from.  If Corona has too much work to do in any frame, all future frames are blocked till that work is done.

Enterframe() is the way forward. 

For example, in my games I load data in chunks, each chunk represents <5% of total data.  I can then animate a progress bar to provide visual feedback to the user.

You must do this out of scope to the scene being loaded and it is a chunk of work so I wouldn’t bother unless your screen is +10s to load.

I should have mentioned i dont use composer, so if that is a limitation as RG says then he know better.

I remember reading that composer has a kind of parent layer that might be able to handle cross scene code, might want to look into that, or maybe RG know more about what I refer to :grinning:

Updated my post above re: composer.* and blocking.

Oh i see. Yeah my spinner isnt always silk smooth but it depends on how much work is being done in the background, and sometimes cose can be altered slightly to make it look better.

However, it is smooth enough to be functional and after all, cant get past the single threaded limitation of corona, so no point wanting something that cannot be had.

It is of course being updated on enterFrame events.

Lets just says it is the lesser of two evils when comparing with using the native activity indicator.

Hello everyone,

Thanks to all for their inputs. Looking at the above discussions many of the experts are suggesting enterFrame, but I am not understanding how exactly I should work regarding to it, for exactly what and where I should use enterFrame ?? 

Can I get the same functioning using functions?? like after loading some assets the value of progress bar will get update as the function to update it will be called?? 

Sir @roaminggamer, I am founding it hard to understand your code would it be possible for you to simplify it?

Sir @anon63346430,

Are you to using enterFrame() to achieve above functioning?? 

Sir @nick_sherman,

Is it possible for you to show me a short demo of what you are suggesting above? I am understanding what to do but not understanding how to do.

Sorry no.  That is as simple as it gets: 

  1. Fake workload to demo problem,
  2. Three examples showing how to display work load (one showing issue; second showing native activity indicator, third showing enterFrame solution).

If this is too hard to understand at this point, you’re better off just living with the delay.  This isn’t a simple thing.

PS - As @sgs pointed out: “Doing this is a significant chunk of work.”  This technique requires both knowledge and discipline to deal with.  If you’e new, this may be beyond your current skills.

Using the enterFrame event is pretty straight forward.
Is just like a timer except instead of setting the timer to call function to run after set time has expired, enterFrame will run the function each time a new frame is drawn. If your app runs at 30fps that means it will call the function 30 times per second. Now if you have a display object you can for example rotate it X degrees each time the function is run, meaning it will rotate a little 30 times per second.

Sorry for the lack of formatting, writing on a mobile phone.

let’s say you have a bit of code somewhere name “Preloader” (for example) that knows how to process() a single step in the loading sequence, for example: 

if “sequence”==1 then you do the first of many time-intensive things, then return

if “sequence”==2 then you do the second of many time-intensive things, then return

up to as many discrete steps as you wish

then in a “loading” scene you’d set up an enterFrame listener and call Preloader:process() on each frame with an increasing sequence number, pseudocode:

-- LoadingScene.lua -- partial, psuedocode local Preloader = require("Preloader") functions scene:create(event) self.preloadSequence = 1 Runtime:addEventListener("enterFrame", self) end function scene:enterFrame(event) -- animate a progress bar (or whatever) as a percentage of current sequence versus total Preloader:process(self.preloadSequence) self.preloadSequence = self.preloadSequence + 1 -- \* see note below, re "who" maintains this if (Preloader:isComplete()) then Runtime:removeEventListener("enterFrame", self) composer.gotoScene("NextScene", whatever) end end

that’s the general pattern for a “typical” preloader.  if you don’t already know what coroutines are and how to use them, then it’d be hard to recommend that approach.

* if you want to get “fancy” and make it reusable, then build your preloader to accept an array of loader functions, then it’s easy to vary the total number, keep track of the sequence, calculate a percentage complete for you, and basically track the whole process for itself.

We have a function called composer.loadScene() https://docs.coronalabs.com/api/library/composer/loadScene.html

It supports preloading scenes. You shouldn’t need to go with a loading bar if you can pre-load the scene.

Rob

This is still going to be blocking the main thread though, isn’t it?

I guess the problem is historical… i.e. when Corona first launched multi-core was not a thing.  But it very much is now and this really needs supporting.  I know @nick had to move to Unity to enable his app to run and I am contemplating it.

Most new phones are 8-core yet the best Corona can do is cooperative multitasking - like what windows 3.1 did.  EnterFrame and co-routines still execute on the main thread right?

I know some libraries (like audio) run on a separate thread and do correct me if I am wrong but I imagine that mostly we are stuck to executing on a single core? 

I appreciate the issues around being thread-safe but I am sure there are some big performance gains to be made here.