LibGDX

Android, Game Development, Java, LibGDX, scene2d

LibGDX: Scene2d – Actors Part 1

Scene2d is a higher-level framework for creating games. It’s not mandatory to use it but sometimes it is very useful because code is more friendly and simpler. It is indicated for menu, buttons, checkboxes, etc. but it’s useful for board games, character’s equipment, and more.

Scene2d is composed of 3 classes regarding Scene2d :

  1. Actor: The Actor class is a node in the graph which has a position, rectangular size, origin, scale, rotation, and color.
  2. Group: The Group class is an actor that may have child actors.
  3. Stage: The Stage class has a camera, SpriteBatch, and a root group and handles drawing the actors and distributing input events.

The stage is a container that has and handles actors. Also, it has an action method that takes a delta time as an argument and it calls the act method of every Actor, allowing the actors to take some action based on time. As you can see act method is something like the update method that we already know.

The constructor of Stage class accepts only 2 arguments, Viewport and Batch. It doesn’t need to pass the camera because Viewport handles the camera internally. The batch argument is optional as well. The Stage class handles batch internally.

So, it doesn’t need to dispose of Batch manually because the stage will. That’s only in the case that we let Stage object to handle Batch alone. On the contrary, if we pass Batch as an argument in Stage then we have to dispose of it manually. As a rule, it’s better to let Stage object to handle batch alone.

Also, it doesn’t need to use setProjectionMatrix or batch.begin() or batch.end() manually because the Stage handles these automatically.

As a result, we have a more simple and maintainable code.

Sample Code

We will see an example with the Actors. We will start with class MyActor which “extends” Actor.

The constructor of MyActor class takes 2 arguments, a Texture and a String. Also, in the constructor, we set an event using addListener for our Actor. In case the Actor is touchable, we have to set it with the following line.

A very important notice is to call setBounds() method with the right arguments.

In this example, spritePos() is where the sprite position is changed and setBounds() method is called.

The next step is to pass our actors in Stage. Take a look at the following code.

As you can see, we have to pass Viewport as an argument in Stage and actors using addActor() method.

[fun_fact]If you don’t know how to use AssetManager & AssetDescriptors take a look in LibGDX: AssetManager[/fun_fact]

In render() method:

The act method isn’t needed in our case because we don’t use Actions in this example.

If we run the code we will see the following output:

scene2d_actor_example

Clicking each asset, we will see in console the following output:

Touch down asset with name : images/character.png
Touch down asset with name : images/null.png
Touch down asset with name : images/skeleton.png

The stage can handle events right and when we touch down any of the assets an event is triggered.
You can find the LibGDX source code in LibGDXExamples!

Android, Game Developer, Game Development, Java, LibGDX, OOP, Programming

LibGDX: AssetManager

Assets are one of the most significant and demanding things in a game. Images, music, sounds, fonts, skins are only some of the reasons that a game may respond slow and have bad behavior if they are not set up correctly.

It is acceptable to have a small delay while the assets are loading before the game starts, but from the time that the game has started, we do not want to have a lag or a delay. If so, then we face the danger of losing our users because the game becomes frustrating to them.

So, we must be very careful on how to handle our assets in our game. It’s not the only thing that we have to take into account when we develop a game but it’s sure a very important one.

It is a heavy process creating new objects at run-time, so, if we need to create new assets and dispose of some others then we face the danger of having lags or our game freezing.

We have to be very careful when we use the keyword “new” at run-time. For example, the LibGDX framework loads an image with the code below

Creating new objects is costly and has negative consequences in run-time gaming. Generally speaking, it is a good habit to evade having big constructors, synchronization calls during object construction. Instead, we can use Weak References.

Also, there are some design patterns like object pooling and prototype which we can use in order to avoid using new” keyword so as to generate new instances. You can take a look at these design patterns here and here.

Back to our subject, LibGDX provides us with the right tools to handle and use assets as efficiently as possible.

One of these tools (class) is AssetManager. It’s only a very useful class that helps us handle our assets. Every single one of the assets is loaded in memory once and we can use them as many times as we want.

It’s the best way to handle images, music, sounds, and more. Also, you can read why and how to use AssetManager in LibGDX documentation.

  • Loading of most resources is done asynchronously, so you can display a reactive loading screen while things load.
  • Assets are reference counted. If two assets A and B both depend on another asset C, C won’t be disposed of until A and B have been disposed of. This also means that if you load an asset multiple times, it will actually be shared and only take up memory once!
  • A single place to store all your assets.
  • Allows to transparently implement things like caches.

AssetManager usage is simple enough.

The first line makes a new object of AssetManager. The second line puts the image myImage.png which is a texture in the queue.

From the time we call finishLoading(), we start the loading process of the assets. The whole program is blocked until all assets are loaded.

Caveat. Method manager.load(“…”); doesn’t load any asset, instead, it puts every asset in the queue and when we call finishLoading(), it starts loading the assets.

Method get() returns an asset and we use casting in order to set image variable with an image from the manager.

Attention! Don’t use AssetManager as static.

According to the documentation, it is bad practice to use AssetManager as static due to the different lifecycles of a static and Android Activity. This approach may lead to bugs and memory leaks.

There are two ways to load assets using AssetManager. We have already seen the first using finishLoading() function. The second is update() method. Using this function we have a better control when assets are loading. We can use it with the function getProgress() which returns a percentage of loading.

Take a look in the next example of code

It is worth noting that we don’t need to use dispose() in each Texture or any asset AssetManager handles. The code is more elegant and we don’t need to write too many lines so as to dispose of each asset individually.

This whole process is very useful and a big improvement during code execution. It’s a big improvement when we have to create new instances of an asset in run-time.

Drawing With AssetManager

Continuing, we will see how we can use AssetManager with a good structure. Also, we will draw some images on our screen.

Starting with class Assets and we will declare the images paths.

AssetDescriptors

We can use get(“asset name”) method in order to get the asset and use it. It’s not the best practice, in case we want to change an asset with another one. Then we have to change each one point that we have already declared.

Another reason is when we just have a single string in get() we cannot be aware of what type of asset the get() is going to return.

So, LibGDX offers AssetDescriptor which handles situations like that.

LibGDX API Class AssetDescriptor<T> describes an asset to be loaded by its filename, type, and AssetLoaderParameters. Instances of this are used in AssetLoadingTask to load the actual asset.

Now we are ready to create a class named AssetDescriptors and we will declare every asset.

The next step is to create the right code in order to load assets in AssetManager and draw these assets on screen.

At this point, we are only going to see and analyze AssetManager and not the camera.

As we can see in the constructor we create a new instance of AssetManager.

Show() calls loadAssets() function. This function sets assets in a queue and after that, it calls finishLoading() function which blocks everything until all assets are loaded.

After that, we are ready to use all assets that are loaded in AssetManager.

Now we are ready to draw images (our assets) inside render() with the standard way, using batch.

You may have already noticed that in dispose() function we don’t dispose of every asset as we used to.

We just have to dispose of manager and all assets will be disposed of by the manager. Nice!

Using AssetManager with update()

In order to use update() method we have to remove the line below from loadAssets();

and add the code below in show() function after loadAssets() call.

You can find the whole source code in the file AssetManagerUpdateExample.java

AnnotationAssetManager

AnnotationAssetManager is another tool that comes with libgdx-utils library. It is a tool that simplifies the whole situation even more. As you can imagine we will use annotations.

Before we start we have to add the following lines in gradle file in order to download libgdx-utils library.

Now we are ready to go!

We will need one more class named AssetsAnnotation and we will use @Asset() in order to put assets in the queue. So, we don’t need to write the same code twice.

You may have already noticed that loadAssets() function is just 2 lines. We don’t need to load every single asset anymore, we just need to call AssetsAnnotation class.

Outputassetmanager examples

You can read more about AnnotationAssetManager here!

Conclusion

It is suggested to always use AssetManager in order to handle and load assets. In that way, assets are loaded once in memory and we use them as many times as we want.

Assets don’t need to be disposed of one by one. Instead of that, we just dispose the manager.

Also, it’s easy to handle our assets because they are located in one place.

The outcome is a more compact and elegant code and this leads to cleaner code. Also, there are fewer places to hide a bug.

It’s the best solution in case we have to create “new” instances of assets at run-time and not only!

You can find LibGDX examples in GitHub!

View More