Friday, December 28, 2012

Texture Manager for libgdx


Managing Texture objects in libgdx can be surprisingly annoying. On the one hand, libgdx does some useful optimizing under the hood. On the other hand, you may run into race conditions with garbage collection that manifests as native code errors.

For example:
  • You're using a Texture before a scene change.
  • When you're exiting the scene, you dispose of the Texture objects used.
  • You create a new scene that just happens to use the same Texture.
  • GC finally fires to fully dispose of the Texture.
  • When you go to render the new scene, you hit a native error.
These problems can be difficult to debug, as the stack trace and error output often make no mention of the Texture; in development of Monkey Match, the last piece of our code was somewhere in the render method, before calling into libgdx's Stage object.


To resolve this, a Texture manager class can be very handy. There are two elements to this:
  1. A bundled texture object that contains a reference to both a Texture and a TextureRegion.
  2. The texture manager itself.
The bundled texture is handy because you'll often find yourself referencing both Texture objects and TextureRegion objects for rendering purposes.


First, let's build ourselves the BundledTexture class:

public class BundledTexture {
 public final Texture       texture;
 public final TextureRegion region;
 public BundledTexture(final Texture texture, int offsetX, int offsetY, int width, int height) {
  this.texture = texture;
  this.region = new TextureRegion(this.texture, offsetX, offsetY, width, height);
 public float width() {
  return region.getRegionWidth();
 public float height() {
  return region.getRegionHeight();

The width() and height() methods are just helper methods. libgdx defines many different width/height methods and it's not always clear which version you want. This was used as a shortcut to make the code more clear.

The rest should be pretty clear: We store the Texture object and create a TextureRegion based on the offset and height/width passed in.

Now, for the TextureManager class:

public class TextureManager {
 private final Map<String, BundledTexture> mDict = new HashMap<String, BundledTexture>();
 public void add(final String key, final BundledTexture texture) {
  if (mDict.containsKey(key)) {
  mDict.put(key, texture);
 public BundledTexture get(final String key) {
  return mDict.get(key);
 public void dispose(final String key) {
  if (!mDict.containsKey(key)) {
  final BundledTexture t = mDict.get(key);
 public void disposeAll() {
  for (final BundledTexture t : mDict.values()) {


This is also pretty simple, but simple is always better, no? We add BundledTextures to our map with a String identifier, which we can later use to find the texture. We check for error conditions and silently fail (you could throw an exception, if so desired; I prefer not to obfuscate my code with them unless I'm dealing with asynchronous or otherwise truly "exceptional" conditions).

When we're ready to dispose of a Texture, we can either single it out individually, or we can dispose of the entire map. You could override the finalize() method, but with libgdx, we often find ourselves calling these methods on-demand.


That's it! Now, we just initialize our TextureManager, add textures to it, retrieve the desired texture when we want to use it, and dispose with the whole shebang when we're done.

You can find the source code for this example on bitbucket (git repository).

Update 1: Minor edits for clarity, to clean up Blogger formatting.

Monkey Match has arrived!

We've just launched our first Android app, Monkey Match! It's a fast-paced matching game that's fun for all ages. Conquer all the continents and defeat your high score!

Check out the free, ad-supported version here or go the full monty and buy the ad-free version for only 99 cents.

Thursday, December 27, 2012

Voyage Games Privacy Policy

Privacy Policy

There are many different ways you can use our services. When you share information with us, for example by installing a new Voyage Games app, we can make those services even better, more performant and responsive. As you use our services, we want you to be clear how we’re using information and the ways in which you can protect your privacy.

Our Privacy Policy explains:

What information we collect and why we collect it. How we use that information. The choices we offer, including how to access and update information. Your privacy matters to Voyage Games so whether you are new to Voyage Games or a long-time user, please do take the time to get to know our practices and if you have any questions contact us.

Information we collect

We may collect information about the services that you use and how you use them, like when you view and interact with our apps and content. This information includes:

Device information

We may collect device-specific information (such as your hardware model, operating system version, unique device identifiers, and mobile network information including phone number).

Log information

When you use our services or view content provided by Voyage Games, we may automatically collect and store certain information in app logs. This may include:
  • details of how you used our service, such as your how long you viewed specific screens and what content buttons you pressed.
  • device event information such as crashes, system activity, hardware settings, device type, language, the date and time of your actions.
Location information

When you use a location-enabled Voyage Games service, we may collect and process information about your actual location, like GPS signals sent by a mobile device. We may also use various technologies to determine location, such as sensor data from your device that may, for example, provide information on nearby Wi-Fi access points and cell towers.

Unique application numbers

Certain services include a unique application number. This number and information about your installation (for example, the operating system type and application version number) may be sent to Voyage Games when you install or uninstall that service or when that service periodically contacts our servers, such as for automatic updates.

Local storage

We may collect and store information (including personal information) locally on your device using mechanisms such as external device storage (for example, SD cards) and application data caches.

Anonymous identifiers

We use various technologies to collect and store information when you use a Voyage Games service, and this may include sending one or more anonymous identifiers to your device. We may also use anonymous identifiers when you interact with services we offer to our partners, such as advertising services or Voyage Games features that may appear on other sites.

How we use information we collect

We use the information we collect from all of our services to provide, maintain, protect and improve them, to develop new ones, and to protect Voyage Games and our users. We may also use this information to offer you tailored content like giving you more relevant app content.

When you contact Voyage Games, we may keep a record of your communication to help solve any issues you might be facing. We may use your email address to inform you about our services, such as letting you know about upcoming changes or improvements.

We use information collected to improve your user experience and the overall quality of our services. For example, by saving your language preferences, we’ll be able to have our services appear in the language you prefer. When showing you tailored ads, we will not associate an anonymous identifier with sensitive categories, such as those based on race, religion, sexual orientation or health.

We will ask for your consent before using information for a purpose other than those that are set out in this Privacy Policy.

Voyage Games processes personal information on our servers in many countries around the world. We may process your personal information on a server located outside the country where you live.

Accessing and updating your personal information

Whenever you use our services, we aim to provide you with access to your personal information. If that information is wrong, we strive to give you ways to update it quickly or to delete it unless we have to keep that information for legitimate business or legal purposes. When updating your personal information, we may ask you to verify your identity before we can act on your request.

We may reject requests that are unreasonably repetitive, require disproportionate technical effort (for example, developing a new system or fundamentally changing an existing practice), risk the privacy of others, or would be extremely impractical (for instance, requests concerning information residing on backup tapes).

Where we can provide information access and correction, we will do so for free, except where it would require a disproportionate effort. We aim to maintain our services in a manner that protects information from accidental or malicious destruction. Because of this, after you delete information from our services, we may not immediately delete residual copies from our active servers and may not remove information from our backup systems.

Information we share

We do not share personal information with companies, organizations and individuals outside of Voyage Games unless one of the following circumstances apply:

With your consent

We will share personal information with companies, organizations or individuals outside of Voyage Games when we have your consent to do so. We require opt-in consent for the sharing of any sensitive personal information.

For legal reasons

We will share personal information with companies, organizations or individuals outside of Voyage Games if we have a good-faith belief that access, use, preservation or disclosure of the information is reasonably necessary to:
  • meet any applicable law, regulation, legal process or enforceable governmental request.
  • enforce applicable Terms of Service, including investigation of potential violations.
  • detect, prevent, or otherwise address fraud, security or technical issues.
  • protect against harm to the rights, property or safety of Voyage Games, our users or the public as required or permitted by law.
We may share aggregated, non-personally identifiable information publicly and with our partners like publishers, advertisers or connected sites. For example, we may share information publicly to show trends about the general use of our services.

If Voyage Games is involved in a merger, acquisition or asset sale, we will continue to ensure the confidentiality of any personal information and give affected users notice before personal information is transferred or becomes subject to a different privacy policy.

Information security

We work hard to protect Voyage Games and our users from unauthorized access to or unauthorized alteration, disclosure or destruction of information we hold. In particular:

Our Privacy Policy applies to all of the services offered by Voyage Games LLC and its affiliates, including services offered on other sites (such as our advertising services), but excludes services that have separate privacy policies that do not incorporate this Privacy Policy.

Our Privacy Policy does not apply to services offered by other companies or individuals, including products or sites that may be displayed to you in ads, sites that may include Voyage Games services, or other sites linked from our services. Our Privacy Policy does not cover the information practices of other companies and organizations who advertise our services, and who may use cookies, pixel tags and other technologies to serve and offer relevant ads.


We regularly review our compliance with our Privacy Policy. We also adhere to several self regulatory frameworks. When we receive formal written complaints, we will contact the person who made the complaint to follow up. We work with the appropriate regulatory authorities, including local data protection authorities, to resolve any complaints regarding the transfer of personal data that we cannot resolve with our users directly.


Our Privacy Policy may change from time to time. We will not reduce your rights under this Privacy Policy without your explicit consent. We will post links to any privacy policy changes on this page and, if the changes are significant, we will provide a more prominent notice (including, for certain services, email notification of privacy policy changes). We will also keep prior versions of this Privacy Policy in an archive for your review.


To contact Voyage Games, email us at: voyagegamesllc [at] gmail [dot] com