B4A Library libGDX - Game Engine



One of the best game engines for Android is now available to B4A users. Unleash your creativity!

You can read a description of this library in this guide.

Download for B4A v10.60 and older (4 MB)
Download for B4A v10.70 and newer (4 MB)

Starting from version 1.13, the library is compiled with Java 8, and thus requires a recent version of B4A and Java 8+.
To install the library, copy the .jar file and the .xml file in your libraries folder.

This library is not compatible with the Debug mode. Ensure that you always compile in Release mode.

Download also the examples and templates.

You can reduce the weight of the library if you want to keep your APK file as small as possible. Read this post to learn how to create your Lite version.

Tutorials:
How to make games
Introduction to the libGDX library
PacDroid: from scratch to fun
Shaders

Take also a look at the Cloney Bird tutorial by andymc.

Plugins:
Box2DLights
SpecialFX

Versions:
 
Last edited by a moderator:

wonder

Expert
Licensed User
Longtime User
Hello Informatix,

I've ported an HTML5 3D-Starfield Example to B4A / LibGDX.
Everything runs perfectly smooth without any issues, except for one minor detail.

The star behavior in the z-axis is different than it should be, unless I delay the start of the 3D-Starfield drawing (in LG_Render) for a few seconds.
B4X:
Sub Process_Globals
    Dim Engine_Start_Timestamp = DateTime.Now As Long
Ens Sub

...

Sub LG_Render
    ...
    If DateTime.Now - Engine_Start_Timestamp > 5000 Then Draw_Starfield
    ...
End Sub
I've also noticed abnormal behavior (not exactly the same, but still abnormal) in my "Project Ryu" game, unless I add this delay workaround.
I've been reading your tutorials back and forth and trying to understand if there is a synchronization problem between the GDX thread and the main thread.

Another solution I tried was to add 2 boolean flags (Globals_Ready = True and LG_Ready = True) at the end of Sub Globals and Sub LG_Create.
B4X:
Sub Process_Globals
    Dim Globals_Ready, LG_Ready = False as Boolean
    ...
End If

Sub Globals
    ...
    ...
    ...
    ...
    Globals_Ready = True

End If

Sub LG_Create
    ...
    ...
    ...
    ...
    LG_Ready = True
End If

Sub LG_Render
    ...
    If Globals_Ready = True and LG_Ready = True Then Draw_Starfield
    ...
End Sub
No success, the abnormal behavior still happens.

I can record a small video to illustrate the problem if necessary.
 

Informatix

Expert
Licensed User
Longtime User
Could you post the whole code?
 

wonder

Expert
Licensed User
Longtime User
Here's all the relevant parts, I hope I'm not missing anything.
I'll post a small video later.
B4X:
Sub Process_Globals
    Dim Creation = DateTime.Now as Long
    ...
End Sub


Sub Globals
        Dim ball_speed = 80%x As Float

        Dim Ball_Width = 4%x As Float
        Dim Ball_Height = Ball_Width As Float
        Dim Ball_Left = 50%x - (Ball_Width / 2) As Float
        Dim Ball_Top = 50%y - (Ball_Height / 2) As Float 
        Dim Ball_Last_Left As Float
        Dim Ball_Last_Top As Float


    'LibGDX Setup
        Dim lGdx As LibGDX
        Dim Gl As lgGL
        Dim Camera As lgOrthographicCamera
        Dim Batch As lgSpriteBatch
        Dim GLView As View

    'Color Mixer
        Dim temp_color As lgColor
    
    'LibGDX Textures
        Dim Tex001 as lgTexture
        Dim Tex002 as lgTexture
        ...

    'LibGDX Objects
        Dim Obj001 As lgTextureRegion
        Dim Obj002 As lgTextureRegion
        ...

    'Starfield
        Dim MAX_DEPTH = 32 As Float
        Dim number_of_stars = 64 As Float    
        Dim initial_star_speed_factor = 100 As Float
        Dim star_speed_factor = initial_star_speed_factor As Float
        Dim star_speed_change_timestamp As Long
        Dim star_speed_change_duration As Int
        Dim star_x(number_of_stars) As Float
        Dim star_y(number_of_stars) As Float
        Dim star_z(number_of_stars) As Float
        Dim smin = -25 As Int
        Dim smax =  26 As Int    
 
        For i = 0 To (number_of_stars - 1)
            star_x(i) = Rnd(smin, smax)
            star_y(i) = Rnd(smin, smax)
            star_z(i) = Rnd(1, MAX_DEPTH)
        Next
End Sub

Sub Activity_Create(FirstTime as Boolean)
    ...
    ...
    'Initialize libGDX
        GLView = lGdx.InitializeView("LG")  
        Activity.AddView(GLView, 0%x, 0%y, 100%x, 100%y)
    ...
    ...
End Sub

Sub LG_Create
    Batch.Initialize
    'Initialize Textures
        Tex001.Initialize("tex001.png")
        Tex002.Initialize("tex002.png")
        ...
    'Initialize Objects
        Obj001.InitializeWithTexture(Tex001)
        Obj002.InitializeWithTexture(Tex002)
        ...

        Obj001.Flip(False, True)
        Obj002.Flip(False, True)

    temp_color = Batch.color
End Sub


Sub LG_Resize(Width As Int, Height As Int)
    'Sets the camera viewport
        Camera.Initialize
        Camera.SetToOrtho2(True, lGdx.graphics.Width, lGdx.Graphics.Height)
End Sub


Sub LG_Render
    'Clears the screen
        Gl.glClear(Gl.GL10_COLOR_BUFFER_BIT)
                            
    'Updates the matrices of the camera
        Camera.Update

    'Uses the coordinate system specified by the camera
        Batch.ProjectionMatrix = Camera.Combined
        
    'Step Setup
        LGStep = lGdx.Graphics.DeltaTime

    'Main GDX Cycle
        If DateTime.Now - Creation >= 5000 Then
            Batch.Begin
            LG_Draw_Starfield
            ...
            Batch.End
        End If
End Sub


Sub LG_Draw_Starfield
    For i = 0 To (number_of_stars - 1)

        If (DateTime.Now - star_speed_change_timestamp) >= star_speed_change_duration Then star_speed_factor = initial_star_speed_factor
    
        star_z(i)= star_z(i) - (ball_speed * LGStep) / star_speed_factor
        If star_z(i) <= 0 Then
            star_x(i) = Rnd(smin, smax)
            star_y(i) = Rnd(smin, smax)        
            star_z(i) = MAX_DEPTH        
        End If
        Dim k  = 128 / star_z(i) As Float
        Dim px = star_x(i) * k + 50%x + ((1/6) * (50%x - Ball_Left)) As Float
        Dim py = star_y(i) * k + 50%y + ((1/9) * (50%y - Ball_Top )) As Float      

        If px >= 0%x AND px <= 100%x AND py >= 0%x AND py <= 100%y Then
            Dim size = (1 - (star_z(i) / 32.0)) * 5 As Float
            Dim shade = (1 - (star_z(i) / 32.0)) * 255 As Float        
        
            If game_mode = "INTRO" OR game_mode = "MENU" Then shade = shade / 2
        
            ARGB(0) = (shade / 255)
            Dim apply_shade As lgColor                        
            Batch.color = apply_shade.setRGBA(ARGB(1)/255, ARGB(2)/255, ARGB(3)/255, ARGB(0))
                    
            'Draw a single star
                Batch.DrawRegion2(Star, px, py, size * 10, size * 10)            
                    
        End If
    Next
    Batch.color = temp_color
End Sub


Sub LG_Dispose
    'Dispose All Sounds
        ...
    'Dispose All Textures
        ...
End Sub


Sub LG_Pause
End Sub


Sub LG_Resume
End Sub
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
I notice that if star_z(i) = 0 then you have a division by zero.
 

wonder

Expert
Licensed User
Longtime User
I notice that if star_z(i) = 0 then you have a division by zero.
Isn't that prevented by:
B4X:
If star_z(i) <= 0 Then
            star_x(i) = Rnd(smin, smax)
            star_y(i) = Rnd(smin, smax)      
            star_z(i) = MAX_DEPTH      
End If
Dim k = 128 / star_z(i) AsFloat
MAX_DEPTH is set to 32 in Sub Globals. The only way for MAX_DEPTH to be zero is if the LG_Render is started before the Sub Globals...

Anyway, I'm working on the video.
 

Informatix

Expert
Licensed User
Longtime User
Ah yes, sorry. I have to try the code if I want to understand where's the issue.
 

wonder

Expert
Licensed User
Longtime User
I've tried to record the video with my mobile phone, but the quality is terrible.
Instead I've tried to illustrate the problem:

By "appear" I mean "move". The stars move in compact blocks in the z-axis, instead of being evenly spread.

One thing I've noticed, this doesn't happen in the same way in all devices.
Usually, the faster the device is, the most unlikely is it to happen without the "delay method".
 

wonder

Expert
Licensed User
Longtime User
I found the solution for the problem I mentioned in my previous posts.

It seems that the value of lgdx.Graphics.DeltaTime is zero during the first few seconds an app is started. Depending on your code, this causes weird behaviour, like frozen sprites or divisions by zero. In my case I think it might have been a division by zero since I was using (1 / lgdx.Graphics.FramesPerSecond) instead of DeltaTime.
I solved it by adding the following conditions in at the beginning of Sub LG_Render:

B4X:
'Step Setup      
        If lGdx.Graphics.DeltaTime > (1/60) AND lGdx.Graphics.DeltaTime <= (1/30) Then
            LGStep = lGdx.Graphics.DeltaTime
        Else If lGdx.Graphics.DeltaTime <= (1/60) Then
            LGStep = (1/60)
        Else If lGdx.Graphics.DeltaTime > (1/30) Then
            LGStep = (1/30)
        End If

LGStep is the variable I'm using to control the movement velocity on screen. This small piece of code keeps everything running smooth between 30 and 60 frames per second.

For more information about this Step Method, please refer to this post: https://www.b4x.com/android/forum/threads/how-to-make-games.32593/
 

TheJinJ

Active Member
Licensed User
Longtime User
Sorry, confusion.
How to I set the joint definition to be a motor joint similar to
eg.
B4X:
RevoluteJointDef.Type = world.JOINTTYPE_RevoluteJoint
So the joint is created using
B4X:
Dim RevoluteJoint as lgBox2DRevoluteJoint = World.CreateJoint(RevoluteJointDef)
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
I see now where the type declaration is missing (lgWorld), but you don't need it in the above case. A RevoluteJoint has always the RevoluteJoint type.
 

TheJinJ

Active Member
Licensed User
Longtime User
I see now where the type declaration is missing (lgWorld), but you don't need it in the above case. A RevoluteJoint has always the RevoluteJoint type.

The motor joint type is missing, I used revolute as an example of the syntax, sorry for the confusion

This Motorjoint type is missing

B4X:
RevoluteJointDef.Type = world.JOINTTYPE_MotorJoint
 
Last edited:

TheJinJ

Active Member
Licensed User
Longtime User
I know you don't really have time to work on this library but noticed another possible fix required....

If a body has multiple fixtures the shape can be set ok but the position cannot. It always reports as the bodies centre.

eg
B4X:
Dim circleShape As lgBox2DCircleShape
....
circleShape.position.set(-2, -2)
fixtureDef.shape = circleShape
body.createFixture(fixtureDef)

No error is thrown when trying to set the position but if you retrieve it, it is always the 0, 0 so will be the body centre.

Any ideas?
 

Informatix

Expert
Licensed User
Longtime User
This works:
circleShape.position = circleShape.position.set(-2, -2)
or:
Dim Position as lgMathVector2
Position.Set(-2, -2)
circleShape.position = Position
 

Crystal Noir

Member
Licensed User
Longtime User
Hi,

Are the example files are ok for the current version ? Beucause I tried to compile several but I can't launch any file, I have always a not found exception like this with the internal files.

Example for the particle file :

B4X:
LogCat connected to: 3204ddaf8d656111
--------- beginning of /dev/log/main


--------- beginning of /dev/log/system


Copying updated assets files (63)


** Activity (main) Create, isFirst = true **


** Activity (main) Resume **


sensor listener setup


OGL renderer: Mali-400 MP


OGL vendor: ARM
OGL version: OpenGL ES 2.0
OGL extensions: GL_EXT_debug_marker GL_OES_texture_npot GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_depth24 GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth_texture GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 GL_OES_vertex_half_float GL_EXT_blend_minmax GL_OES_EGL_image_external GL_OES_EGL_sync GL_OES_rgb8_rgba8 GL_EXT_multisampled_render_to_texture GL_EXT_discard_framebuffer GL_OES_get_program_binary GL_ARM_mali_program_binary GL_EXT_shader_texture_lod GL_EXT_robustness GL_OES_depth_texture_cube_map GL_KHR_debug


framebuffer: (5, 6, 5, 0)
depthbuffer: (24)
stencilbuffer: (8)
samples: (0)
coverage sampling: (false)
Managed meshes/app: { }
Managed textures/app: { }
Managed shaders/app: { }
Managed buffers/app: { }
Error occurred on line: 44 (main)
com.badlogic.gdx.utils.GdxRuntimeException: Error reading file: particles/particles.p (Internal)


    at com.badlogic.gdx.backends.android.AndroidFileHandle.read(SourceFile:76)
    at com.badlogic.gdx.graphics.g2d.ParticleEffect.loadEmitters(SourceFile:153)
    at com.badlogic.gdx.graphics.g2d.ParticleEffect.load(SourceFile:139)
    at anywheresoftware.b4a.libgdx.particles.lgParticleEffect.Load(SourceFile:151)
    at flm.b4a.libgdxtest.main._lg_create(main.java:398)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:636)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:302)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:238)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:121)
    at anywheresoftware.b4a.ShellBA$1.run(ShellBA.java:66)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:146)
    at android.app.ActivityThread.main(ActivityThread.java:5694)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.io.FileNotFoundException: particles/particles.p
    at android.content.res.AssetManager.openAsset(Native Method)
    at android.content.res.AssetManager.open(AssetManager.java:316)
    at android.content.res.AssetManager.open(AssetManager.java:290)
    at com.badlogic.gdx.backends.android.AndroidFileHandle.read(SourceFile:74)
    ... 22 more

Thx for helping me
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…