Wednesday, January 2, 2019

Check us out on!

Happy New Year! We have started porting our Android games over to so that they can be played on any device, so head on over to our page there and check out what we have to offer. Right now it is just one game, but in the next couple of days we should have a few more up.

In the meantime, let me tell you about Rodney Dangerfield. This isn't a wild tangent, I promise. You see, Rodney Dangerfield had always wanted to be a stand up comedian, but he suffered from a simple problem. He wasn't funny. No one liked his jokes, he was booed off stage, he was a failure. Most people would quit at this point (I know I did, but that story is a wild tangent, so it can wait), and in fact Rodney did quit comedy for a while. The problem was that he had an itch, and it wouldn't go away. So, he ended up quitting his job, destroying his marriage, and almost ruining his life to find out why he wasn't funny and to use that information to fix the problems and become a successful stand up.

To go about this, he went on an epic quest (of sorts) to find out what exactly was funny. He wanted to know what exactly it was that made people laugh. In effect, he was looking for the essence of comedy. He wanted to strip away all the cruft and find the simplest form of humor, figuring that from there he would be able to master the medium. Well, he did in fact. He removed all the excess layers of story and exposition that other comics relied on and became the king of one liners. He found the root of the joke and used that to become very successful.

So what does that have to do with us? Well, I am of a certain age, and I started coding as a hobby a year or two ago because I felt that my needs weren't being met by software developers. Let's be honest, casual games suck, microtransactions and pay to win sucks, huge AAA cinematic gaming experiences aren't fun anymore, and mobile gaming is a cess pit. I realize that some of this is age, that everything was more important, shinier in my youth, but I also really believe that there are things that make the games of yore more appealing.

First, the unlimited resources of today - both computational and financial - allow game creators to polish turds so to speak. With enough computer power any game can be beautiful no matter how stupid the underlying gameplay is. With enough financial power, studios can and do force us to pay attention to these games that we would otherwise ignore. I know a lot of people will disagree with me, but I don't personally care about the horses' testicles in Red Dead Redemption. What is the gameplay like? Is there actually a game under there? As a counter example, check out this essay of the perfection that is the beginning of the original Super Mario Brothers game for the NES. Now we joke about how a game will have a ten hour tutorial before you get started.

Next, there is the myth that creating a mobile game will make you wealthy beyond belief. Hey, look at Flappy Bird or 2048! They are so simple, anyone can do it. This leads to poorly made games filled with ads to the point that even the poor gameplay is choked out. Now, I am not against having ads in apps, in fact most of our apps do contain ads, but the user experience has to come first.

Finally, microtransactions and play to win are the worst ideas ever. Forcing a player to pay money to get more 'turns' for the game, or making important items only available in the cash shop is a great way to ruin a game.

The truth is that, to me, games have lost much of their appeal. Don't get me wrong. I still play Pixel Dungeon daily, and since I reviewed the game in early 2013, that means I have been playing it for five years. The problem, though, is that most games have lost that thread of what a game really is.

So, like Rodney Dangerfield, we are looking to trim all the fat from the gaming experience and see what is left. Looking at timeless games like Tetris show us that a game doesn't need shiny graphics or even a story, they just have to be fun. So, what then is fun? Well, let's find out together.

Friday, July 20, 2018

Basic Sprite Animations in libGDX

In the last post we discussed how to use the texture packer to create sprites. And now we will take a look into how to put these sprites into a libGDX application.

First things first, you need to copy the files you create with the texture packer into the app's asset folder. These assets are typically stored in the Android folder of the app, so in the case of Dot's Dots, the directory is something like this:


Don't forget there are at least two files that need to be copied. The PNG file(s), which are the images, and the ATLAS file, which is a map of the images.

Now that the image files are in place, let's look at the code used to animate the sprite.
package com.petenotpete.dotsdots;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;

public class DotsDots extends ApplicationAdapter {
private SpriteBatch batch;
private TextureAtlas textureAtlas;
private Animation<TextureRegion> animation;
private float elapsedTime = 0;

public void create () {
batch = new SpriteBatch();
textureAtlas = new TextureAtlas(Gdx.files.internal("dotsprite.atlas"));
animation = new Animation<TextureRegion>(1/60f, textureAtlas.getRegions());

public void render () {, 0, 0, 1);;

elapsedTime +=;
batch.draw(animation.getKeyFrame(elapsedTime, true), 0, 0);

public void dispose () {
Now let's look at the code. The magic here is this line:
animation = new Animation(1/60f, textureAtlas.getRegions());
This sets the animation speed (60fps in this case) and the sprite frames from the texture atlas. The next key part are these lines:
elapsedTime +=;
batch.draw(animation.getKeyFrame(elapsedTime, true), 0, 0);
The elapsed time lets the animation know what frame should be displayed, and the 'true' following it shows that the animation should loop. So in this animation, it uses all the sprites on the sprite sheet, but oftentimes we will have more than one image or animation on a sprite sheet and will need to differentiate between them. If you use the libGDX texture packer to create the sprites, the sprite atlas names the frames after each image's individual filename. The best way to use this to your advantage is to add a prefix to each different image in a spritesheet and number them sequentially (like: walk001.png, walk002.png, walk003.png, run001.png, run002.png, run003.png, etc.). In the code you can separate the animations as follows:
public void create() {
batch = new SpriteBatch();
textureAtlas = new TextureAtlas(Gdx.files.internal("dotsprite.atlas"));

TextureRegion[] walkFrames = new TextureRegion[10];

walkFrames[0] = (textureAtlas.findRegion("0001"));
walkFrames[1] = (textureAtlas.findRegion("0002"));
walkFrames[2] = (textureAtlas.findRegion("0003"));
walkFrames[3] = (textureAtlas.findRegion("0004"));
walkFrames[4] = (textureAtlas.findRegion("0005"));
walkFrames[5] = (textureAtlas.findRegion("0006"));
walkFrames[6] = (textureAtlas.findRegion("0007"));
walkFrames[7] = (textureAtlas.findRegion("0008"));
walkFrames[8] = (textureAtlas.findRegion("0009"));
walkFrames[9] = (textureAtlas.findRegion("0010"));

walkAnimation = new Animation(1/60f, walkFrames);

//or you can just pass the frames directly

runAnimation = new Animation(0.1f,
And there you go, you have a sprite moving around.

Tuesday, May 22, 2018

Creating Sprites with libGDX texturepacker

One of the differences between using libGDX and and not using a game engine is that libGDX uses sprite sheets. This is good, because in OpenGL, binding textures is fairly resource expensive and it is better to bind one large resource once than many small resources.

There are plenty of tutorials online about creating sprites, and I am certainly not much of an artist, so I will leave that to others to explain. But, I will say this, if you are like me and end up with a GIF file or have each of your individual sprites saved as layers in a single image there is a trick to getting them out without saving individually.

To separate layers of an image file into separate images the easy way, save the image file as an OpenRaster file (.ora extension). GIMP can do this for free, and likely most other image editing software can as well. After saving, open the .ora file using compression software (7zip or WinRAR), open the 'data' folder, and you will see each individual layer saved as a separate .png file. Easy.

Otherwise, it is important that each of your animation frames is in numerical (or alphabetical) order so that the sprite sheet will be created in the proper order. In my case, I number each frame like 001.png, 002.png, 003.png and so on.

For this tutorial, I made a simple 12 frame animation of a dot running (the app I am making is called Dot's Dots*, right?). You can see it in GIF form below, but I won't provide the images or the sprite sheet for you, because I think it is important that you try this for yourself. And honestly, you don't even need to make it 12 frames, you could have a 3-4 frame animation of a stick man walking and it will be fine.

Now, hopefully you created a simple animation of a few frames. In order to create your sprite sheet the first thing you should do is download the texture packer JAR file. Save it somewhere convenient, and use the following command at the command line to create the sprite sheet:

// OS X / Linux java -cp runnable-texturepacker.jar [inputDir] [outputDir] [packFileName]

// WINDOWS java -cp runnable-texturepacker.jar [inputDir] [outputDir] [packFileName]

[inputDir] is where you saved your individual image files, [outputDir] is where you would like the sprite sheet to be saved and [packFileName] is going to be the name of the output file.

In my case, I want to take my image files and save the sprite sheet directly into my apps assets folder. Because I am using Linux, I would type this:

java -cp runnable-texturepacker.jar 'Images/Sprites/DotsDots' '/home/netbook/AndroidStudioProjects/dotsdots/android/assets' dotsprite

After the texture packer runs, you will find two types of file in the output directory. There will be the .png files, which will be the actual sprite sheets, and there will be the .atlas file. The .atlas file is a text file that tells libGDX the location of each individual image on the sprite sheet.

If you want to just make a simple sprite sheet, feel free to stop reading here. I will discuss slightly little more technical stuff below, but it likely won't affect sprite or animation performance.

Note that the texturepacker defaults to sprite sheets that are 1024px x 1024px. In 2018 that seems fairly paltry, and if you want to change the sheet size, or any other options, you just need to include a file called 'pack.json' in the same directory as your individual image files. The pack.json file can have the following options:


pot: true,
paddingX: 2,
paddingY: 2,
bleed: true,
bleedIterations: 2,
edgePadding: true,
duplicatePadding: false,
rotation: false,
minWidth: 16,
minHeight: 16,
maxWidth: 1024,
maxHeight: 1024,
square: false,
stripWhitespaceX: false,
stripWhitespaceY: false,
alphaThreshold: 0,
filterMin: Nearest,
filterMag: Nearest,
wrapX: ClampToEdge,
wrapY: ClampToEdge,
format: RGBA8888,
alias: true,
outputFormat: png,
jpegQuality: 0.9,
ignoreBlankImages: true,
fast: false,
debug: false,
combineSubdirectories: false,
flattenPaths: false,
premultiplyAlpha: false,
useIndexes: true,
limitMemory: true,
grid: false,
 scale: [ 1 ],
scaleSuffix: [ "" ],
scaleResampling: [ bicubic ]


You only need to include the options you want to change, any unlisted options will just return to the default settings. As for the sprite sheet size, I believe that on most modern devices that sheets of 4096px x 4096px will work fine. However, old devices, particularly those using old versions of OpenGL, will not work. I thought about this personally, and decided that it was more important for me to maintain backwards compatibility than it is to minimize texture binding resource use, so I decided to stay with the default. Of course that decision is up to each developer, so you can decide on your own.

Next, if your images don't fit all onto one sprite sheet, it might be a good idea to separate them into subdirectories in your input directory. By doing this, you can ensure that the texturepacker saves related files on the same sprite sheets. Because the libGDX texturepacker tries to create the most efficient packing result, related sprites could be spread across several sprite sheets, which would be very inefficient.

Finally, if you want to run the texturepacker as part of your app, it can be done. We won't cover it here, because it seems to be of limited value to hobbyist developers that are likely working alone, but the libGDX wiki discusses it in detail.

*I have no idea what Dot's Dots is going to turn out to be, I am creating it on the fly as part of this tutorial. Shhhh!

Monday, May 14, 2018

Compiling Your libGDX Project

So now that you have imported a libGDX project into Android Studio, you will probably notice that it doesn't look like a normal Android Studio project, and also that it won't compile right away.

This tutorial will explain the changes needed to be made so that you can compile your libGDX project for Android, desktop and HTML.


So if you tried to compile your new project you probably got a Gradle error that looks something like this:

What happens here is that currently (as of early 2018) projects imported from libGDX use a Gradle version of something like 2.14.1 and libGDX needs a Gradle version of 3.5 or above. Conversely, you will also get an error if you are using any Gradle version above 4.0, which would be the default of Android Studio. In either case, we want to change the Gradle version. To do this, we open the '' file under the 'Gradle Scripts' heading in the Project window.

We want to change the distributionURL line to:
If you followed my previous tutorial in setting up the libGDX project in Android Studio, this should be all you need to do in order to make the APK able to be compiled.

If you are still having trouble, here are some other problems I have faced.

Error:(2, 0) Plugin with id 'jetty' not found

This error is caused when you are using a Gradle version above 4.0. Follow the steps above to change the Gradle version to 3.5, but additionally follow these steps:

1. Open the project level 'build.gradle' file (again under the 'Gradle Scripts' heading in the Project window)
2. Change the 'classpath' version:
classpath ''
3. In the same file, under 'repositories' remove:
NOTE: There are two places to do #3, under 'buildscript' and under 'allprojects'

Error: Plugin with id 'gwt' not found

If you run into this error, there is a simple solution. Just go into the project level 'build.gradle' file (again under the 'Gradle Scripts' heading in the Project window) and add the following line under the 'dependencies' inside the 'buildscript' tag:
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'


The easiest way to compile to desktop is to create a runnable JAR file. To do this, open the Gradle window by clicking the vertical 'Gradle' button on the right side. In that menu, expand ':desktop', then expand 'other', and finally click on 'dist'.

Once it is finished compiling, you can find the JAR file in this directory:
[APPLICATION PATH]/desktop/build/libs

If you end up having an error, read below.

Running the desktop app from Android Studio

This is easy, once you know what to do. Go into the Project Window and expand the 'Desktop' folder. Several folders will open and at the end there will be a java file 'DesktopLauncher'. Right click that and select 'Run DesktopLauncher.main()'. Unfortunately, this will cause an error. It will say something like Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file: badlogic.jpg. If this is the case, the answer is simple.

Go into the run menu at the top of the Android Studio window and click on 'Edit Configurations...' This will open the Run/Debug Configurations Menu. Click on 'DesktopLauncher' from the dropdown menu on the left. Now, on the right side you can see an item called 'Working directory:'. To fix this error just append 'android/assets' to the directory listed. It should look like:
[APPLICATION PATH]/android/assets

This should allow it to run, but if you have another error see below.

"Exception in thread 'main' java.lang.NoClassDefFoundError: com/badlogic/gdx/ApplicationListener"

To solve this problem, we need to run the app as a JAR application. To do this, go into the run menu at the top of the Android Studio window and click on 'Edit Configurations...' This will open the Run/Debug Configurations Menu. In this menu, first click the green plus sign in the top left. Select 'JAR Application' from the drop down menu. You will see something like this:
You need to enter the 'Path to JAR:' which will be:
[APPLICATION PATH]/desktop/build/libs/desktop-1.0.jar
Next, in the 'Before Launch' section at the bottom, hit the green plus and add 'Run Gradle Task'. The 'Gradle Project' should be found at:
[APPLICATION PATH]/desktop/build.gradle
Finally, in the 'Tasks' box, type:

And that's it. You should be able to run your app on the desktop as a JAR application by clicking the 'Select Run/Debug Configuration' button in the menu and selecting 'JAR Application'. Then just click the green run arrow to the right and wait for it to compile.


Let's be honest, libGDX doesn't play well with HTML. But, if you are like me, you want to be a completionist and force it to work. Well, be forewarned: you will have to deal with a lot of code workarounds in order to make your application compile to HTML. For the time being, though, let's just look at how to actually get it to compile.

In Android Studio, open the Gradle window by clicking the vertical 'Gradle' button on the right side. In that menu, expand ':html', then expand 'other', and finally click on 'dist'. That will build your web app.

To find the files, you need to go into:
[APPLICATION PATH]/html/build/dist
All of the files will be in that folder and its subfolders.

A word of warning, though. Even with the default libGDX app (showing a picture on a red background), it doesn't seem to work in every browser. For example, on my Linux machine, it works fine on Seamonkey (2.49.1) but not on Chrome (63.0.3239.132). At some point in the future I might come back to figure out why, but for the time being I am going to accept that it compiles and leave it at that.

Wednesday, May 9, 2018

Setting up a libGDX project in Android Studio

***** This tutorial is based on the libGDX tutorial series at Game from Scratch. Their tutorial is helpful, but outdated, so I am going through and updating it based on Android Studio 3.0.1 and libGDX 1.9.8 *****

Before we start, please understand that I am only one person and I am going through this tutorial for my own benefit. Because of that, I won't be able to cover all instances exactly. Particularly, I use a crummy old Linux laptop for coding and don't have access to either a Windows or Mac machine to test how things work on other operating systems. Where possible I will try to provide help, but since I won't be able to test it, I can't make any guarantees.

The first step is to ensure that you have Android Studio and the Java Development Kit (if you have trouble, make sure you installed the 'JDK' specifically).

Next, download the libGDX project setup tool and put it in a convenient directory. (Note there is an official setup guide, although it, too, is a bit out of date.) Now that you have all the necessary files, let's get started on importing a project.

1. From the command line, go to the directory where you saved the libGDX setup file (gdx-setup.jar) and type:

java -jar gdx-setup.jar

You should see this screen now:

If you don't, the most likely issues are that you are not in the correct directory or that you haven't installed the Java JDK. Recheck those steps before doing anything drastic.

2. Now it is time to set up the project. 
  • First, choose the name that you want to use. I will call my project Dot's Dots, but feel free to call your project whatever you like. 
  • For the Package name, I follow the Google Play naming convention, so will use com.petenotpete.dotsdots.
  • Game class isn't overly important, but I will also change it to DotsDots because I like to be thorough.
  • Destination is fairly important for ease of use. I want to create the project in the same folder as the rest of my Android Studio projects just for convenience sake. If you do this, you should specify the actual folder of the project, and not the generic projects folders. For example, in my case you would want to specify:
    If you don't know where that is, or don't care, just save the project somewhere convenient for you.
  • Android SDK location is obviously important, but it should be automatically filled in. If for some reason it isn't, you can find the location of the SDK by opening an Android Studio project and selecting 'File' -> 'Other Settings' -> 'Default Project Structure...'
  • For the subprojects, I just leave the default. We will discuss a bit about web based and desktop applications, so they are good to have, and who knows, you might just want to publish your app to the App Store some day.
  • Under extensions, I just leave the default 'Box2d' checked.
3. Now that everything is filled out properly, click that 'Generate' button. When I do this I get two warnings:

In both cases I hit 'No'. I am not sure how things will work otherwise, but I read of some fairly recent (as of early 2018) issues on Stack Overflow where the libGDX project wasn't compiling because it didn't work with the newest Android and Gradle versions so figure it is better to stick with the recommended versions.

Once that is done, go get yourself a cup of coffee and watch everything get set up.

4. Once the libGDX project generator says it is finished, open up Android Studio and open the project.  Sometimes it doesn't show up in the menu immediately, but if you browse the directory structure you should be able to find and open the project.

5. When you open the project in Android Studio, it is likely you will get a popup similar to the following:

It honestly doesn't matter that much what you pick because we are going to have to change the Gradle version again anyway, but I personally select "Don't remind me again for this project" because otherwise you get an error immediately upon opening.

6. So now you should have the project open in Android Studio, and the next step is going to be getting the project to compile on desktop, HTML and Android.

Saturday, May 5, 2018

Using LibGDX with Android Studio

All of my previous apps I had designed just using Java directly in Android Studio, but my ambitions have been growing and I decided that I need to use some sort of game engine to continue developing what I want. The problem is that there are so many game engines available for Android development. Seriously, go Google it (ok, you probably already have if you are reading this), I will wait.

I realize that none of the game engines are perfect, and choosing one would involve trade offs. In order to find the best game engine for me, I made a short list of must haves and preferences. I ended up with three musts:

1. Open source and free to use - I am not making any money here, well not anything to speak of, and I prefer to minimize any possible expenses.
2. Strong 2d engine - I don't foresee myself making any 3d games in the near future, so I prefer a game engine that focuses on 2d as it suits my needs.
3. Extensive documentation - I am not an expert and am doing this as a hobby, so I need to find a well developed engine that has a lot of tutorials available.

On top of this, I would prefer a game engine that uses Java so that I don't have to completely relearn everything. This isn't incredibly important, but I have limited time and would prefer not to use that trying to understand a new language.

Anyway, after some research, I had two game engines that I was interested in, Godot and libGDX. They both hit my three must haves, and it was hard for me to choose between the two. Originally I was going to go with Godot, but after a quick Googling it looked like libGDX had been around longer and had much more written in terms of tutorials and beginner's help.

While this was true, it turned out to not be that much of a blessing. Most of the tutorials and walkthroughs for libGDX are outdated and don't work with the current version, which has been causing me headaches. HOWEVER! I actually think this might be a good thing, because instead of being able to just copy and paste the code that I want, I have to go through and figure everything out. This is going to help me in the long run, and it will definitely make me a better developer.

At the same time, I understand that not everyone wants to go through the trouble, so I am going to do my best to chronicle my progress here so that people going forward can have an up to date walkthrough on how to get started.

Wednesday, April 25, 2018

Hard Truths about Android App Design

Here are some hard truths that every hobbyist Android developer needs to face at some point:

1. You are not going to make the next Flappy Bird - I mean seriously, I know that everyone thinks about their golden ticket. I would be lying if it didn't motivate me sometimes, but seriously, take a moment and scroll way way way way way down to the bottom of a search in the Play Store. The app you design is very likely going to be lower than that in search rankings. The likelihood of becoming a viral success is infinitesimal.
2. Your app idea isn't as good as you think it is - Yes, I know your mom (wife/best friend/whoever) told you that it is brilliant. But these are also the people who tell you how adorable your baby looks even though you know it uncannily resembles Yoda. It is hard to get honest criticism from the people closest to you, and it is hard for you, as the developer, to critically assess what you have made. But here is the thing, even if your app is awesome, you still have to contend with number 3.
3. Someone else (probably ten someone elses) have already made the app you are thinking of - Again, do a deep dive into the Play Store and take a look at what is available. I won't go so far as to say that there is nothing new under the sun, but people have been designing applications for Android phones for a long time now, and it is highly unlikely that you managed to come up with a totally original idea. And even if you did...
4. Marketing is as important as actual app quality -  Do you have any idea how much SuperCell spends in advertising? A quick Googling says something like 500 million dollars a year. If you dig into the details, it averages out to a cost of nearly $2 per install if you use a CPI (cost per install) marketing campaign for your Android app. Now, to justify that kind of spending, you have to be able to earn more than $2 per user on average. Can your app do that? If not, you have to look into other ways of marketing your app. Let me tell you from personal experience, marketing is tedious. I started Android development because I wanted to make apps, not beg people to look at them.
5. You are going to get bad reviews - So let's say you overcome all of these obstacles and people are downloading your app. Certain people are going to leave horrible reviews for no apparent reason. Out of six apps that I have have made, I am lucky enough that one of them gets a slow but steady stream of downloads. The problem is that it is a utility app (it allows you to use your phone and a Bluetooth speaker like a megaphone) and I get one star reviews without comment and one star reviews with walls of text criticizing me as a person and one star reviews saying "I don't like this game, it is stupid", and it drives me up the wall. I know that all the other apps in the market face the same issue (the average rating of similar apps is like 3.5, even though they all work generally fine), but it is frustrating that people are apparently writing bad reviews not based on the app itself.

At any rate, Android development can be fun and rewarding, but it isn't the free pass to early retirement that you wish it would be. You need to have thick skin, and you will be surprised how you feel when you release your perfect app, check the console the following day and see that zero people installed it. It is deflating, but that isn't a reason to stop. Keep working on your ideas, keep trying new things. Who knows, you actually might create the next Flappy Bird.