Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Working with loading background and progress bar.
Started by swanandthakur1105 Mar 05 2018 07:13 AM

* * * * * 1 votes
38 replies to this topic
gui
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

Hello everyone,

 

When a scene changes from one to another it takes time to get ready, what I need to do is till the next scene gets completely ready, it should be hidden by a background and the progress bar should tell how much the next scene is ready. Once the next scene is completely ready that scene should be shown removing progress bar and the background. But I am not finding a way to do it, I checked for another topic related to the same functioning but it didn't give me expected results.

 

There are solutions using timer.performWithDelay(), like look for the time in which the scene gets ready, have a background for that much time and then remove the background once the scene is ready, but I am looking for some different solution

 

I am grateful to everyone who will be taking part in the above discussions.

 

Thanks and Regards,

Swanand Thakur



[TOPIC: post.html]
#2

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,960 posts
  • Corona SDK

Unfortunately scene loading isn't asynchronous. In order to have a progress bar, you'd need to do something like:

 

Load Scene, but don't create any images or do any heavy calculations.

Show progress bar and background. Don't insert into scene group so it stays above everything else.

Using an enterFrame listener, break your image loading and heavy calculations into smaller chunks. 

After each chunk has been processed, update the progress bar.

Once all loading is done, remove the progress bar and background.

 

It depends on what your scene is like as to whether this is manageable and whether it makes sense to put all the image filenames, default positions, physics data etc into a table to iterate through one image at a time. 



[TOPIC: post.html]
#3

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

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.



[TOPIC: post.html]
#4

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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.



[TOPIC: post.html]
#5

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

[TOPIC: post.html]
#6

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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

 

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.



[TOPIC: post.html]
#7

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

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.

 

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



[TOPIC: post.html]
#8

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

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:

  1. 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.

Edited by roaminggamer, 05 March 2018 - 12:41 PM.


[TOPIC: post.html]
#9

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,197 posts
  • Corona SDK

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.



[TOPIC: post.html]
#10

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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 😀

[TOPIC: post.html]
#11

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

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



[TOPIC: post.html]
#12

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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.

[TOPIC: post.html]
#13

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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

[TOPIC: post.html]
#14

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

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?



[TOPIC: post.html]
#15

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

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.

 

Sir @SGS,

 

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



[TOPIC: post.html]
#16

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

Unfortunately scene loading isn't asynchronous. In order to have a progress bar, you'd need to do something like:

 

Load Scene, but don't create any images or do any heavy calculations.

Show progress bar and background. Don't insert into scene group so it stays above everything else.

Using an enterFrame listener, break your image loading and heavy calculations into smaller chunks. 

After each chunk has been processed, update the progress bar.

Once all loading is done, remove the progress bar and background.

 

It depends on what your scene is like as to whether this is manageable and whether it makes sense to put all the image filenames, default positions, physics data etc into a table to iterate through one image at a time. 

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.



[TOPIC: post.html]
#17

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

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.


Edited by roaminggamer, 06 March 2018 - 08:41 AM.


[TOPIC: post.html]
#18

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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.

[TOPIC: post.html]
#19

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,373 posts
  • Corona SDK

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.



[TOPIC: post.html]
#20

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,613 posts
  • Enterprise

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



[TOPIC: post.html]
#21

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,960 posts
  • Corona SDK

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



[TOPIC: post.html]
#22

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,197 posts
  • Corona SDK

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.



[TOPIC: post.html]
#23

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,373 posts
  • Corona SDK

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

 

yes, though loadScene() might help hide it, depends on where all this loading is occurring...

 

if in create(), then loadScene() will take just as much time as gotoScene() and block for the duration, though the timing of it could potentially be done far in advance of gotoScene() if there is a convenient "down-time" prior in which to hide its execution.  (ie, it will still block, so you can't animate during, but might be less obvious)

 

otoh, if this loading occurs in show(), then you'll still have to wait for that after loadScene() when gotoScene() is eventually called, and that'll block too.

 

either way, if you need to "come up for breath" every so often, emitting a new frame, to actually animate your own progress bar, then you'll have to break it up into pieces somehow (enterFrame, timers, coroutines, ..)



[TOPIC: post.html]
#24

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

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. 

 

@anaqim,

 

I know the working of enterFrame, my question was that where and how enterFrame should be use to achieve the above functionality, as for the first time I am dealing with loading bar and don't have much idea about it by the way thanks for involving in discussion



[TOPIC: post.html]
#25

swanandthakur1105

[GLOBAL: userInfoPane.html]
swanandthakur1105
  • Enthusiast

  • 83 posts
  • Corona SDK

Thanks to everyone for their inputs, I have achieved the above functionality using coroutines.

 

Special thanks to @davebollinger for bringing this term "coroutine" to my notice I searched on it and for now I have achieved the functionality I was looking for.

 

Regards,

Swanand Thakur.




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]