Android Question libGDX, ScreenManager & Auto transitions

Foz

Member
Licensed User
Longtime User
I've come across something that appears to be a bug when using the screen manager.

Using the MultiScreen example, I've modified it so there is a countdown of 100 (per frame render). On hitting zero, at the end of the render, I'm telling the screen manager to switch to the other screen.

This works, but it works differently to the touch event - the touch event switches instantly, whereas the countdown version as approximately a 1 second delay.

What is the correct way to detect when to automatically change the screen? A timer that just runs asynchronously to the game loop?

I've added the code from my modified MultiScreen so you can see what I'm trying to do.

B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MultiScreen
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

'Activity module
Sub Process_Globals
    Dim LastScreen As Int = 0
End Sub

Sub Globals
    Dim lGdx As LibGDX
    Dim GL As lgGL
    Dim LG_Input As lgInputProcessor

    Dim LGSM As lgScreenManager
    Dim LG_Screen(2) As lgScreen

    Dim Camera As lgOrthographicCamera
    Dim Batch As lgSpriteBatch
    Dim Texture As lgTexture
    Dim Region As lgTextureRegion
    Dim Sprite As lgSprite
    Dim Font As lgBitmapFont
    Dim TextHeight, TextWidth As Int
   
    Dim countdown As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.Color = Colors.Blue

    'Adds the libGDX surface to the activity
    Dim V As View = lGdx.InitializeView("LG")
    Activity.AddView(V, 10%x, 10%y, 80%x, 80%y)
    Log("Initialized = " & V.IsInitialized)
    lGdx.LogLevel = lGdx.LOGLEVEL_Debug

    'Adds a label
    Dim lbl As Label
    lbl.Initialize("")
    lbl.Gravity = Gravity.CENTER_HORIZONTAL
    lbl.Text = "Touch the libGDX view to alternate its screens"
    lbl.TextColor = Colors.White
    lbl.TextSize = 18
    Activity.AddView(lbl, 5%x, 92%y, 90%x, 20dip)
End Sub

Sub Activity_Resume
    'Informs libGDX of Resume events
    If lGdx.IsInitialized Then lGdx.Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    'Informs libGDX of Pause events
    If lGdx.IsInitialized Then lGdx.Pause
End Sub

Sub LG_Create
    'Initializes the InputProcessor for touch events
    LG_Input.Initialize("LG")

    'Creates two screens
    LGSM.Initialize(lGdx)
    LG_Screen(0) = LGSM.AddScreen("LGS1")
    LG_Screen(1) = LGSM.AddScreen("LGS2")
    LGSM.CurrentScreen = LG_Screen(LastScreen)
End Sub

Sub LG_Resize(Width As Int, Height As Int)
End Sub

Sub LG_Render
End Sub

Sub LG_Resume
End Sub

Sub LG_Pause
End Sub

Sub LG_Dispose
End Sub

Sub LG_KeyDown(KeyCode As Int) As Boolean
    Return False
End Sub

Sub LG_KeyUp(KeyCode As Int) As Boolean
    Return False
End Sub

Sub LG_KeyTyped(Character As Char) As Boolean
    Return False
End Sub

Sub LG_TouchDown(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    Return False
End Sub

Sub LG_TouchUp(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    'Changes the current screen
    If LGSM.CurrentScreen = LG_Screen(1) Then
        LGSM.CurrentScreen = LG_Screen(0)
    Else
        LGSM.CurrentScreen = LG_Screen(1)
    End If
    Return True
End Sub

Sub LG_TouchDragged(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    Return False
End Sub

#Region Screen 1
'-------------------------------------------------------------------------------------
' SCREEN 1
'-------------------------------------------------------------------------------------
Sub LGS1_Show
    Log("1 show")
    LastScreen = 0
countdown = 100
    Batch.Initialize

    Texture.Initialize("libgdx.png")
    Texture.SetFilter(Texture.FILTER_Linear, Texture.FILTER_Linear)
    Region.InitializeWithTexture2(Texture, 512, 275)
    Sprite.InitializeWithRegion(Region)
    Sprite.SetSize(0.9, 0.9 * Sprite.Height / Sprite.Width)
    Sprite.SetOrigin(Sprite.Width / 2, Sprite.Height / 2)
    Sprite.SetPosition(-Sprite.Width / 2, -Sprite.Height / 2)
End Sub

Sub LGS1_Resize(Width As Int, Height As Int)
    Log("1 resize")

    'Sets the camera viewport
    Camera.Initialize2(1, Height / Width)
End Sub

Sub LGS1_Render(Delta As Float)
'    Log("1 render " & Delta)
    GL.glClearColor(1, 1, 1, 1)
    GL.glClear(GL.GL10_COLOR_BUFFER_BIT)

    Batch.ProjectionMatrix = Camera.Combined
    Batch.Begin
    Sprite.Draw(Batch)
    Batch.End
   
    countdown = countdown - 1
    If countdown < 0 Then
Log(DateTime.Now & "    Switch to screen 2 start")
LGSM.CurrentScreen = LG_Screen(1)
Log(DateTime.Now & "    Switch to screen 2 end")
    End If
End Sub

Sub LGS1_Pause
    Log("1 pause")
End Sub

Sub LGS1_Resume
    Log("1 resume")
End Sub

Sub LGS1_Hide
    Log("1 hide")
    Texture.dispose
    Batch.dispose
    Log("1 disposed")
End Sub
#End Region

#Region Screen 2
'-------------------------------------------------------------------------------------
' SCREEN 2
'-------------------------------------------------------------------------------------
Sub LGS2_Show
    Log("2 show")
    LastScreen = 1
countdown = 100

    Batch.Initialize

    Dim FG As lgFontGenerator
    Font = FG.CreateFont("font/liquidcrystal.otf", 48 * Density, "2nd scre013456789")
    Font.SetColorRGBA(0, 0, 1, 1) 'Blue
    TextHeight = Font.GetBounds("2nd screen").Height
    TextWidth = Font.GetBounds("2nd screen").Width
End Sub

Sub LGS2_Resize(Width As Int, Height As Int)
    Log("2 resize")

    'Sets the camera viewport
    Camera.Initialize
    Camera.SetToOrtho(False)
End Sub

Sub LGS2_Render(Delta As Float)
    'Log("2 render " & Delta)
    GL.glClearColor(0.5, 0.8, 0.6, 1)
    GL.glClear(GL.GL10_COLOR_BUFFER_BIT)

    Batch.ProjectionMatrix = Camera.Combined
    Batch.Begin
    Font.Draw(Batch, "2nd screen", (Camera.ViewportWidth - TextWidth) * 0.5, (Camera.ViewportHeight + TextHeight) * 0.7)

    Font.Draw(Batch, "" & countdown, (Camera.ViewportWidth - TextWidth) * 0.5, (Camera.ViewportHeight + TextHeight) * 0.3)

    Batch.End

    countdown = countdown - 1
    If countdown < 0 Then
Log(DateTime.Now & "    Switch to screen 1 start")
LGSM.CurrentScreen = LG_Screen(0)
Log(DateTime.Now & "    Switch to screen 1 end")
    End If
End Sub

Sub LGS2_Pause
    Log("2 pause")
End Sub

Sub LGS2_Resume
    Log("2 resume")
End Sub

Sub LGS2_Hide
    Log("2 hide")
    Font.dispose
    Batch.dispose
    Log("2 disposed")
End Sub
#End Region
 

Informatix

Expert
Licensed User
Longtime User
Any screen change is supposed to be done outside the Render event, on a user action. When this change is triggered, my code waits until the Render event is fully processed to avoid side effects (but it won't finish in your case because you changed the current screen from within the Render event) or until a timeout occurs, hence the delay that you noticed and the message that you get in Logs, before raising Hide, Show, etc.
EDIT: I confirm that the timeout is set to 1 second.
 
Upvote 0

Foz

Member
Licensed User
Longtime User
Thanks Informatix - I thought it was odd. Lesson learnt, no switching screens mid-render!

I guess holding game logic in a timer makes much more sense - let the Render event just do exactly that - render, and have the game logic working at a constant speed.
 
Upvote 0

wonder

Expert
Licensed User
Longtime User
Strange... I have a quite similar method to change the screen, but I experience no delay or side-effects at all.
B4X:
Sub LoadingScreen_Render(Delta As Float)
    'LGStep Control
        If lGdx.Graphics.FramesPerSecond < target_fps Then
            LGStep = (1 / target_fps)
        Else
            LGStep = (1 / lGdx.Graphics.FramesPerSecond)
        End If

    'Displays the Loading Screen with Motion Animation
        Display_Loading_Screen(True)
      
    If ScreenChangeRequest >= 0 AND LoadingScreenModule.AnimationComplete Then
        LGSM.CurrentScreen = LG_Screen(ScreenChangeRequest)
    End If
End Sub

Note: The target_fps var refers to the general sprite animation FPS which is 24.
 
Last edited:
Upvote 0

Foz

Member
Licensed User
Longtime User
I never tried to use a timer for such a case. Let me know whether that works fine.

No such luck. It reports a shader compilation error, but I suspect that it is because it is being called outside of the libGDX thread

Any ideas?

B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MultiScreen
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

'Activity module
Sub Process_Globals
    Dim LastScreen As Int = 0
    Dim tmrLogicProcess As Timer
End Sub

Sub Globals
    Dim lGdx As LibGDX
    Dim GL As lgGL
    Dim LG_Input As lgInputProcessor

    Dim LGSM As lgScreenManager
    Dim LG_Screen(2) As lgScreen

    Dim Camera As lgOrthographicCamera
    Dim Batch As lgSpriteBatch
    Dim Texture As lgTexture
    Dim Region As lgTextureRegion
    Dim Sprite As lgSprite
    Dim Font As lgBitmapFont
    Dim TextHeight, TextWidth As Int

    Dim countdown As Int
   
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.Color = Colors.Blue

    'Adds the libGDX surface to the activity
    Dim V As View = lGdx.InitializeView("LG")
    Activity.AddView(V, 10%x, 10%y, 80%x, 80%y)
    Log("Initialized = " & V.IsInitialized)
    lGdx.LogLevel = lGdx.LOGLEVEL_Debug

    'Adds a label
    Dim lbl As Label
    lbl.Initialize("")
    lbl.Gravity = Gravity.CENTER_HORIZONTAL
    lbl.Text = "Touch the libGDX view to alternate its screens"
    lbl.TextColor = Colors.White
    lbl.TextSize = 18
    Activity.AddView(lbl, 5%x, 92%y, 90%x, 20dip)
   
   
    tmrLogicProcess.Initialize("tmrLogicProcess", 1000 / 30) ' 30 fps
    tmrLogicProcess.Enabled = True
   
End Sub

Sub tmrLogicProcess_Tick
       
    countdown = countdown - 1
    If countdown < 0 Then
    tmrLogicProcess.Enabled = False
        If LastScreen = 0 Then
            Log(DateTime.Now & "    Switch to screen 2 start")
            LGSM.CurrentScreen = LG_Screen(1)
            Log(DateTime.Now & "    Switch to screen 2 end")
        Else
            Log(DateTime.Now & "    Switch to screen 1 start")
            LGSM.CurrentScreen = LG_Screen(0)
            Log(DateTime.Now & "    Switch to screen 1 end")
        End If
    tmrLogicProcess.Enabled = True
    End If

End Sub

Sub Activity_Resume
    'Informs libGDX of Resume events
    If lGdx.IsInitialized Then lGdx.Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    'Informs libGDX of Pause events
    If lGdx.IsInitialized Then lGdx.Pause
End Sub

Sub LG_Create
    'Initializes the InputProcessor for touch events
    LG_Input.Initialize("LG")

    'Creates two screens
    LGSM.Initialize(lGdx)
    LG_Screen(0) = LGSM.AddScreen("LGS1")
    LG_Screen(1) = LGSM.AddScreen("LGS2")
    LGSM.CurrentScreen = LG_Screen(LastScreen)
End Sub

Sub LG_Resize(Width As Int, Height As Int)
End Sub

Sub LG_Render
End Sub

Sub LG_Resume
End Sub

Sub LG_Pause
End Sub

Sub LG_Dispose
End Sub

Sub LG_KeyDown(KeyCode As Int) As Boolean
    Return False
End Sub

Sub LG_KeyUp(KeyCode As Int) As Boolean
    Return False
End Sub

Sub LG_KeyTyped(Character As Char) As Boolean
    Return False
End Sub

Sub LG_TouchDown(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    Return False
End Sub

Sub LG_TouchUp(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    'Changes the current screen
    If LGSM.CurrentScreen = LG_Screen(1) Then
        LGSM.CurrentScreen = LG_Screen(0)
    Else
        LGSM.CurrentScreen = LG_Screen(1)
    End If
    Return True
End Sub

Sub LG_TouchDragged(ScreenX As Int, ScreenY As Int, Pointer As Int) As Boolean
    Return False
End Sub

#Region Screen 1
'-------------------------------------------------------------------------------------
' SCREEN 1
'-------------------------------------------------------------------------------------
Sub LGS1_Show
    Log("1 show")
    LastScreen = 0
countdown = 100
    Batch.Initialize

    Texture.Initialize("libgdx.png")
    Texture.SetFilter(Texture.FILTER_Linear, Texture.FILTER_Linear)
    Region.InitializeWithTexture2(Texture, 512, 275)
    Sprite.InitializeWithRegion(Region)
    Sprite.SetSize(0.9, 0.9 * Sprite.Height / Sprite.Width)
    Sprite.SetOrigin(Sprite.Width / 2, Sprite.Height / 2)
    Sprite.SetPosition(-Sprite.Width / 2, -Sprite.Height / 2)
End Sub

Sub LGS1_Resize(Width As Int, Height As Int)
    Log("1 resize")

    'Sets the camera viewport
    Camera.Initialize2(1, Height / Width)
End Sub

Sub LGS1_Render(Delta As Float)
'    Log("1 render " & Delta)
    GL.glClearColor(1, 1, 1, 1)
    GL.glClear(GL.GL10_COLOR_BUFFER_BIT)

    Batch.ProjectionMatrix = Camera.Combined
    Batch.Begin
    Sprite.Draw(Batch)
    Batch.End
End Sub

Sub LGS1_Pause
    Log("1 pause")
End Sub

Sub LGS1_Resume
    Log("1 resume")
End Sub

Sub LGS1_Hide
    Log("1 hide")
    Texture.dispose
    Batch.dispose
    Log("1 disposed")
End Sub
#End Region

#Region Screen 2
'-------------------------------------------------------------------------------------
' SCREEN 2
'-------------------------------------------------------------------------------------
Sub LGS2_Show
    Log("2 show")
    LastScreen = 1
countdown = 100

    Batch.Initialize

    Dim FG As lgFontGenerator
    Font = FG.CreateFont("font/liquidcrystal.otf", 48 * Density, "2nd scre013456789")
    Font.SetColorRGBA(0, 0, 1, 1) 'Blue
    TextHeight = Font.GetBounds("2nd screen").Height
    TextWidth = Font.GetBounds("2nd screen").Width
End Sub

Sub LGS2_Resize(Width As Int, Height As Int)
    Log("2 resize")

    'Sets the camera viewport
    Camera.Initialize
    Camera.SetToOrtho(False)
End Sub

Sub LGS2_Render(Delta As Float)
    'Log("2 render " & Delta)
    GL.glClearColor(0.5, 0.8, 0.6, 1)
    GL.glClear(GL.GL10_COLOR_BUFFER_BIT)

    Batch.ProjectionMatrix = Camera.Combined
    Batch.Begin
    Font.Draw(Batch, "2nd screen", (Camera.ViewportWidth - TextWidth) * 0.5, (Camera.ViewportHeight + TextHeight) * 0.7)

    Font.Draw(Batch, "" & countdown, (Camera.ViewportWidth - TextWidth) * 0.5, (Camera.ViewportHeight + TextHeight) * 0.3)

    Batch.End
End Sub

Sub LGS2_Pause
    Log("2 pause")
End Sub

Sub LGS2_Resume
    Log("2 resume")
End Sub

Sub LGS2_Hide
    Log("2 hide")
    Font.dispose
    Batch.dispose
    Log("2 disposed")
End Sub
#End Region
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
No such luck. It reports a shader compilation error, but I suspect that it is because it is being called outside of the libGDX thread

Any ideas?

Yes, that error is due to the timer being called from outside the libgdx thread, you can try using the libgdx.Callsub method instead.

Walter
 
Upvote 0

Foz

Member
Licensed User
Longtime User
Hmmm... there isn't a CallSub function in the libGDX library.

There is a CallSubUI, which is for the libGDX thread to call out to the main thread, but nothing for the reverse - from the main thread to the libGDX thread.

Would that be easy to add in? Or am I looking in the wrong place?
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Hmmm... there isn't a CallSub function in the libGDX library.

There is a CallSubUI, which is for the libGDX thread to call out to the main thread, but nothing for the reverse - from the main thread to the libGDX thread.

Would that be easy to add in? Or am I looking in the wrong place?
Yes, sorry that's what i meant CallSubUI, basically you should enabled the timer from another sub which is called from the libgdx thread using CallSubUI, to be honest i really don't like this approach i've always had issues in trying to use timers, i believe Informatix discourages the use of timers in Libgdx.

Walter
 
Upvote 0

Foz

Member
Licensed User
Longtime User
Does anyone have any suggestion for a way of changing screens outside of the render function automatically?

Timers don't work, and I've also tried CallSubDelayed() right at the end of the render event, but that also errors.

What I could really do with is an event that gets called in between the Render events.

If this is not possible, I'll just scrap using libGdx screens and code one big Render manually

~ Foz
 
Upvote 0

wonder

Expert
Licensed User
Longtime User
The "Big Render" will bring you problems (or at best, complicate things) whenever you need to change the current level. That was my case before.

Like I mentioned above, I am able to change screens without any problems.
Have you double-checked your texture loading, initialization and dispose methods?
Remember that initializing a texture for the second time without disposing it first will crash your game.

Here's what works for me:
B4X:
Sub Process_Globals
    'Auxiliary Engine
        Dim Auxiliary_Engine as Timer

    'GDX MultiScreen - Note: The prefix "i" stands for index
        Dim iRequestScene  = -2      As Int 'Request scene (screen) trigger: This informs the aux engine (timer) that there is a screen request to be processed.
        Dim iAllowRequests = -1      As Int 'Standby mode: The render event will be ready to accept any incoming screen change requests.
        Dim iLoadScreen    =  0      As Int 'The "loading screen" index.
        Dim iGameScreen    =  1      As Int 'The "in-game screen" index.

        Dim ScreenChangeRequest = iRequestScene 'The game starts in the loading screen, with a request already in place.
End Sub

B4X:
Sub LG_Create
    'Create Screens
        LGSM.Initialize(lGdx)
        LG_Screen(iLoadScreen) = LGSM.AddScreen("LoadingScreen")
        LG_Screen(iGameScreen) = LGSM.AddScreen("GameScreen")

        LGSM.CurrentScreen = LG_Screen(iLoadScreen)
End Sub

B4X:
Sub LoadingScreen_Show
    'Initialize Loading Animation
        LoadingScreenModule.Initialize

    'Initializes the renderer
        Batch.Initialize

    'Activates the Auxiliary Engine and informs it there's Scene Request
        Auxiliary_Engine.Initialize("Auxiliary_Engine", 16) '16 milisecs is a totally arbitrary value
        Auxiliary_Engine.Enabled = True
        ScreenChangeRequest = iRequestScene
End Sub

B4X:
Sub LoadingScreen_Render(Delta As Float)
    ...
    ...
    'Displays the Loading Screen with Motion Animation
        Display_Loading_Screen(True)

    If ScreenChangeRequest >= 0 AND LoadingScreenModule.AnimationComplete Then
        LGSM.CurrentScreen = LG_Screen(ScreenChangeRequest)
    End If
End Sub

B4X:
Sub Auxiliary_Engine_Tick
    'Scene Loader
    '=====================================================================================
        If LGSM.CurrentScreen = LG_Screen(iLoadScreen) AND ScreenChangeRequest = iRequestScene Then
            Auxiliary_Engine.Enabled = False  'We don't need the Aux Engine anymore after this cycle.
            Startup_Scene("Intro")            'This is my stage loader. NOT LibGDX related.
            ScreenChangeRequest = iGameScreen 'After the stage is loaded, the current request becomes "Please change to the GameScreen".
        End If
    '=====================================================================================
End Sub

B4X:
Sub GameScreen_Show
    ...
    ScreenChangeRequest = iAllowRequests ' = -1
    ...
End Sub

B4X:
Sub GameScreen_Show
    ...
    ...
    ...
    ...
    If ScreenChangeRequest >= 0 Then
        LGSM.CurrentScreen = LG_Screen(ScreenChangeRequest)
    End If
End Sub


It looks complicated but that's due to my game structure.

1. The game starts in the LoadingScreen with a screen change request already in place, although game doesn't know yet which screen will be requested.
2. Once the LoadingScreen detects the request, it activates a timer (aux engine) on the main thread which loads a lot of info necessary for the next stage. This in non-libgdx related.
3. Right before the Database loader kicks in, the timer is deactivated, so that it runs only one time (cycle).
4. The DB loader does its work on the main thread, while a loading animation is displayed in the libGDX thread.
5. As soon as the DB loader finishes its job, the game is informed that the requested screen is the GameScreen.
6. The LoadingScreen_Render event changes the LGSM.CurrentScreen into the GameScreen.
7. Upon stage failure or stage completion, the LGSM.CurrentScreen changes into the LoadingScreen, with either "please restart the level" or a "please advance to the next level" request.
8. GOTO 2 ;)
The difference between using a Timer and a CallSubUI() is that the Timer and its code runs along with the LibGDX thread (aka "at the same time") while the CallSubUI() code will not. (@Informatix, please correct me on this if I got it wrong).

In fact, in a LibGDX project, using a timer is just a cheap trick to run stuff in a different (main) thread.
As soon as I get the ProBundle, I will be using a CallSubExtended instead.
 
Last edited:
Upvote 0

Foz

Member
Licensed User
Longtime User
As I mentioned in my first post, yes it does work (no error), but it incurs a 1 second penalty - as it is waiting for the render to finish, it doesn't, so after 1 second, the render times out, and then the screen switches in place.

Just check your existing loading screen to game screen transition time, but as soon as it finishes loading, the transition should be instant and without a delay.

I agree that having one huge render function will be far more ugly, and harder to code to keep it clean.

This is why I am just wanting to check that there isn't any other possible method that I haven't tried yet.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Strange... I have a quite similar method to change the screen, but I experience no delay or side-effects at all.
B4X:
Sub LoadingScreen_Render(Delta As Float)
    'LGStep Control
        If lGdx.Graphics.FramesPerSecond < target_fps Then
            LGStep = (1 / target_fps)
        Else
            LGStep = (1 / lGdx.Graphics.FramesPerSecond)
        End If

    'Displays the Loading Screen with Motion Animation
        Display_Loading_Screen(True)
     
    If ScreenChangeRequest >= 0 AND LoadingScreenModule.AnimationComplete Then
        LGSM.CurrentScreen = LG_Screen(ScreenChangeRequest)
    End If
End Sub

Note: The target_fps var refers to the general sprite animation FPS which is 24.
Check your Log. Do you see a line saying that a timeout has occured?
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Yes, that error is due to the timer being called from outside the libgdx thread
Indeed, the tick event of the B4A timer is raised in the main thread, even when you start this timer in the libGDX thread. So we can forget timers with libGDX (I never really feel the need for one anyway).
Here's the code to test whether you're in the main thread:
B4X:
Dim JO As JavaObject
JO.InitializeStatic("android.os.Looper")
Log(JO.RunMethod("getMainLooper", Null) = JO.RunMethod("myLooper", Null))
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Does anyone have any suggestion for a way of changing screens outside of the render function automatically?
Apart the one second delay, what's the problem? Is this delay a big issue?
Anyway, each screen is supposed to be a visual scene with a different interaction and purpose. For example, the main menu screen and the options screen are different screens, but a loading screen is not. It's just something that you display while the resources are loaded to build the screen to use. So it makes sense that a screen change is only triggered by an user action.
 
Last edited:
Upvote 0

Foz

Member
Licensed User
Longtime User
Apart the one second delay, what's the problem? Is this delay a big issue?
It appears that the app has frozen (which it has), causing users to tap on the screen to check, which then is being caught by the next screen and the touch events. And depending where they had been tapping depends on the result of what has been pressed.

Is it a big problem? No... but it has wider implications when I want to start using the network events (again, outside the libGDX thread) to raise screen changes, and there is a 1 second application freeze.

This is leading me to think just having one main render function which uses a select statement to call separate render subs - which is what I suspect is being done with the screen manager anyway.

I just want to make sure that I'm not missing anything before I write off the screen manager.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
It appears that the app has frozen (which it has), causing users to tap on the screen to check, which then is being caught by the next screen and the touch events.
How can you catch events for a screen that is not displayed yet? Hide, Show and the other events are not called until the timeout has occured.

I want to start using the network events (again, outside the libGDX thread)
Disk or network operations should be done inside the libGDX thread. Never outside because that could block the main thread and triggers an ANR if the operation takes too long and the user tries to interact with the app.

This is leading me to think just having one main render function which uses a select statement to call separate render subs - which is what I suspect is being done with the screen manager anyway.

I just want to make sure that I'm not missing anything before I write off the screen manager.

You miss nothing. The screen system is just a convenient way to do things, but you can do the same with a select in each event to call separate subs.
 
Upvote 0

wonder

Expert
Licensed User
Longtime User
The difference between using a Timer and a CallSubUI() is that the Timer and its code runs along with the LibGDX thread (aka "at the same time") while the CallSubUI() code will not. (@Informatix, please correct me on this if I got it wrong).
Fred, did I get it right?
 
Upvote 0
Top