Chapter 9. Even Angrier Birds!

Welcome to this chapter! I hope you enjoyed the previous chapter and are making your own games resembling Angry Birds. I also hope you used everything you learned in the previous chapters to really make it into a fully formed game.

In this chapter, we will cover a technique that will hopefully help you when you find yourself creating lots of instances of a certain type of object that are generally short-lived. We will look at object pooling and how LibGDX can provide the tools to help us use them. In this chapter, we'll take a look at the following topics:

  • The how, what, and why of object pools
  • Hey, look at all these acorns!

The how, what, and why of object pools

Object pooling is the principle of reusing inactive or "dead" objects, instead of creating new objects every time.

-https://github.com/libgdx/libgdx/wiki/Memory-management#object-pooling

I guess the best place to start is to talk about what an object pool is. An object pool is a pool of objects, bet you didn't see that coming, that can be reused after they become inactive. The pool can either be prefilled or filled on demand; hopefully, when you require one of these objects, there will be a "free" one available.

I suppose you are now wondering why you would want to do this. I suspect you are wondering, "Hey, I can just call "new" to create an object; perhaps it is an acorn sprite you are creating, and I can do this as much as I want and I don't see an impact." Perhaps, on the scale we are working on, you might get away with that. However, it isn't a mindset you should really adopt here. You have to remember that one of the wonderful things with LibGDX is that it is cross-platform with mobile devices. So, perhaps your game is going to go from running on your fabulous desktop/laptop development machine with your gigabytes of RAM and high-end graphics card to someone's three-year-old mobile smart phone that might have only megabytes of RAM available for your game and even less dedicated to video. So, first off, you might have "out of memory issues" where you create so many objects that the underlying OS might just call it quits on your game—not a good user experience!

The second issue that you might find is excessive slowing down of your game as, particularly on the Android platform, the garbage collector runs to clear out all the "inactive" objects that you created but no longer needed. This is where object pools can come into the picture and provide help. Imagine having to clear up hundreds of instances of an object type that has been created-on-the fly when, in fact, from a gameplay perspective only, say, three are in play at any point in time. If you had these objects in a pool, you would create the three required and then reuse them when you need to. Suddenly, all this excess processing that goes on for clearing up after your game goes away.

Object pools with LibGDX

Right, so hopefully you have an idea of what an object pool is and why an object pool can be useful. Let's look at how an object pool is created in LibGDX.

Before we dive into the code, I recommend that you refer to the wiki page on object pooling and memory management for LibGDX, which is available at the following URL:

https://github.com/libgdx/libgdx/wiki/Memory-management#object-pooling

I strongly suggest that you give it a browse as it will be an eye-opener on memory management.

So what does LibGDX offer to us game makers when it comes to creating object pools? Hopefully, those of you who checked out the preceding link already know the answer!

There are the three classes LibGDX provides:

  • Pool.Poolable
  • Pool
  • Pools

The Pool.Poolable class is an interface that you implement on the object type class that you wish to be handled in a pool. Here is the interface in code:

static public interface Poolable {
  /** Resets the object for reuse. Object references should be nulled and fields may be set to default values. */
  public void reset ();
}

As you can see, it only has one method that you are required to provide an implementation to; that is the reset() method, which is required to clean up the object ready to be made available again in the pool. We will see more of this in the next section.

Next up is the Pool class; this is the pool itself. It contains the instantiations of the objects that we would like to pool. This class is typed, so we can only have all objects of the same type in there; otherwise, we will have all sorts of issues. This class is abstract, which means that we have to define our own class that extends this one. The reason for this is that we need to define how to create a new object for the pool; perhaps it requires some external input such as a reference to a texture that is used for the visual representation. There are two parameters that are required to construct the pool and they are the maximum number of objects in the pool and the initial capacity. It should be noted now that the maximum number is a soft limit. If you request an object and there are none free, a new one will be created. However, when it comes to returning the objects to the pool, if the pool is full, they will be reset but not added back to the pool. I would also like to highlight that the initial capacity doesn't prefill the pool for you; all it does is help to set up the backing array. This is a good thing as, then, you won't get slight pauses in your game should the backing array wish to grow.

To take an object from the pool, there is a method called obtain() that returns either a fresh instance or one from the pool.

When it comes to the time that the game no longer uses this object, as it may have gone out of play, then call the free() method on the pool with the object to be returned.

Just before we move on to the final class that LibGDX has to offer, I want to take this opportunity to highlight the caveat that is mentioned on the LibGDX wiki. It is possible to leak objects from the pool; just because it is returned to the pool doesn't mean other objects do not automatically clear their references to that returned object. This means you will see some odd behavior in your game if you are not careful.

Finally, we have the Pools class. This class, as you can imagine, contains all the pool instances that are provided to it, allowing you to have static access to them anywhere in your code. For the sake of what I would like to cover in this chapter, we will not be using this class. I just wanted you to be aware that this class exists, for when you start having lots of pools.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset