Thursday, May 9, 2024

Incremental Games

 I wrote a post a few years ago about the essence of a game. The basic gist of it was hypothesizing about what makes a game a game, and more importantly, what makes it enjoyable. Basically, in answer to my own question, we have seen mobile game companies leverage certain game mechanics, which might not exactly be dark patterns but are at least closely related. Basically, we know that people respond positively to certain types of stimulus, and so we can design games to provide this stimulus and keep the dopamine running, which makes people continue to play.

The mobile gaming scene, of course, uses this in nefarious ways to get people to spend money on what I consider to be "dumb stuff". I try to be nonjudgmental about others' choices, but when it comes to these specific types of microtransactions in mobile games, it is really hard to see the positive benefits that the purchaser is receiving. Still, I don't want to ruin anyone else's good time, and I am sure it would be easy to judge the way I spend my money (mostly scratch off tickets and dinners at Medieval Times), so let's instead look critically at the mobile game developers and the way they are tricking people into spending money.

Anyway, the reason that I bring this up is that one of my favorite game genres is incremental games, which rely on many of these same dopamine producing tricks to make button clicking and number growing into a game. The main difference here is that in general the incremental game community, at least the part centered around the r/incremental_games subreddit and to a more distributed extent, the galaxy.click website is firmly against microtransactions, forced ads and dark patterns in games. Basically, while the underlying mechanics might be similar, the intentions are pure in the latter case, and are manipulative in the former. 

What is interesting, though, is that for an at least moderately popular subgenre of gaming there is very little written about it. I am going to make a big assumption and say that games that are not monetized provide little incentive to media outlets to provide coverage as there is no obvious financial benefit. Imagine me yelling capitalism while doing jazz hands right now. 

Anyway, I have been thinking of writing about the incremental games in some detail for a while now, and over the upcoming weeks I think I will try to put bits and pieces together to come up with a coherent history and explanation of the genre. Happy clicking! :)



Thursday, April 25, 2024

Remainder Reminder

 Well, I got my homepage into a position that I like, and rolled it out. It has a cool kind of old-style terminal vibe that I like (click and take a look, I'll wait!). I think it also looks cool on mobile, where I moved the sections to tabs on the side and still holds most of the same old terminal vibes without the exact same form factor. I also made it navigable via keyboard (as well as mouse/touch) to really give it that terminal feeling. The problem is, I have no content, haha. I actually just would like to use it for a kind of landing page that shows various projects I am working on, but that kind of gets weird because of my diversity of interests. I still need to think about how to represent various different types of projects in a way that is at least somewhat intuitive or at least makes sense. We'll see how that goes.

A couple days ago I was writing about my old blogs and how they just disappeared into the ether, which had me thinking about it just as I was going to bed and a lightbulb popped over my head. Wayback Machine! So rather than going to bed at my usual early hour, I crawled through a bunch of snapshots and uncovered some old gems. Well, gems for my nostalgia, I don't think anyone really cares about me playing FFXI or drinking to excess for a frankly disturbing number of days in a row. And just looking through now, I found some writing that is fairly transphobic*, even though it is couched language expressing that I don't care how other people live, which was I guess fairly tolerant for 2005, but in 2024 just isn't cutting it. So, perhaps fortunately, my blog wasn't popular enough to be indexed too often, and there are only bits and pieces available to read. Still, I am considering trying to dredge through and maybe repost anything interesting I come across (if there is anything like that) for curiosity value.

In other news, I have been training for a half marathon. Before COVID I was a pretty competitive runner, and would generally finish in the top 10-20 participants in any given half marathon. Then COVID hit and I stopped exercising. There was an outdoor mask rule that people took seriously, and it is hard to do cardio with a mask on, so I basically just gave up. Fast forward to about a year ago (April/May 2023) and my work sponsored people to join the Incheon Half Marathon. I signed up for the 10k race because I knew I was in terrible shape, and ended up having to run walk to a 56:53 finish (I just looked it up). That is a shameful pace and I felt terrible about myself. I realized that I needed to get my act together and start doing something because this wasn't good.

I started running daily again after that wake-up call and pushed and pushed most of last year. My pre-COVID half marathon time was between 85-88 minutes, and I really wanted to get back to that level, nevermind that I am five years older now (45!!! almost 46!!!). I didn't manage to break the 90 minute barrier last year (I ran something like 90:20 in November), but I was right there, and felt confident entering 2024 that I would be in a good place come Spring. Also, there is a certain poetry behind the idea that I went from run walking a 10k at the 2023 Incheon Half Marathon to being back on my game and running under 90 minutes in the half course at the 2024 race. 

Sadly, that was not to be. The original date that registration closed was like April 22, with the caveat that there was only room for 10,000 runners. The race never filled up in the past, so I waited. When I checked it on April 6th, just out of curiosity, the website had a pop up that said they reached the quota and registration would end on April 5th at 5:00pm. I missed the deadline by like 12 hours. This was frustrating on multiple levels. First, I really like the Incheon Half Marathon. It starts at Munhak Stadium and then goes straight down the road through some underpasses, over some overpasses, then over the Songdo Campustown Bridge and all the way down through Songdo to the sea before looping back and ending at the stadium. It is a beautiful run, and it is in my neighborhood. Also, it is a big race and they have some international talent come to compete for prize money. The second reason I got frustrated was because I had planned my training specifically for the date of May 12, and now had to scramble to find another race. One annoyance of living in Songdo is that it is surrounded by the sea and even though it is in the 'metro area', getting to races in Seoul or other places is too much hassle. 

Anyway, I looked at the race calendar and weighed my options. There was a small race in Sangam (Seoul World Cup Stadium) on the same day, and then another race on May 25 in Incheon at Seaside Park on Yeongjongdo (where the airport is). I weighed my options, small uncool race in an inconvenient place but on the correct date, or wait two weeks and run a more fun race closer to home. Well, the deciding factors were that I was training for a specific date and that May 12 is a Sunday, while May 25 is a Saturday. Sundays are easier for me to manage with family obligations and such, and so I chose the smaller less convenient race. Plus, the real scale-tipper was that May 12 in the morning will probably have tolerable weather, while May 25 is getting really close to the blast furnace zone of Korean summer. Either way, Game On.

*I am embarrassed and appalled that I would ever write something like this, and even though probably no one read it then and no one will read this now, I am sorry that I said such gross things. That being said, it makes me feel good to know that I've grown as a person enough that I see previous writing and am like ewwww, I cannot believe that I wrote that. 

Tuesday, April 23, 2024

It's Been a While

Snail
Hard Truths: I started blogging back in like 2001-2002 on Xanga of all places. I started as a Lineage 1 blog and detailed my exploits traveling around with my trusty canine companion, which mostly involved being murdered in upsetting ways in what was, I think, the least forgiving PVP game ever. From there, I moved around a bit and started self hosting. I came to Korea in 2004 and then around 2010, I got married and my life went in a different direction. I stopped paying my hosting bills and lost those six years of content, and Xanga obviously stopped existing long, long ago, which means that about a decade of my writing went poof. To be honest, I kind of like the ephemerality of it all, and while my Lineage blog might fulfil some nostalgic yearning, it isn't exactly the works of Shakespeare, or even Dan Brown for that matter. My early years in Korea might have had some curious value, but the world changes and it was mostly stuff written about places that no longer exist and friends that I no longer meet, and so it pretty much falls into the same basket. 

 Anyway, for the past fifteen years or so I have been wanting to start a blog again. It isn't fashionable, and I don't ever expect anyone to read it, but I find the concept of putting my ideas into words cathartic. However, I've changed a lot in this long time. I got a 'serious' job, I have kids, I am almost through a grueling PhD program, and so on and so forth. BUT! I was talking to some students this morning and happened to be talking about planning for the future and mentioned that it is a good idea to do some self-reflection before making a plan. Think about who you are and who you want to be, and then try to make the necessary moves to put yourself in a position where you can be someone who you like. I know that when I was younger I just made decisions based on what I thought would put me into a better position relative to my peers without ever actually considering what position I actually wanted to be in. It took me a long time to realize that, for instance, chasing money or status at work is not the only way to progress along the path of life, and this is something I wish I thought about earlier. Actually, when I first came into my current job, some people I work with were here for ideological rather than financial reasons. Like they wanted to help people and do the right thing and make the world better, and weren't here just for the paycheck. It took me a long time to come to terms with the fact that the way I was looking at life might not be the best way to do so. Honestly, it took me a long time to even realize that it might not be the only way to do so. Still, once I made that leap, then I realized that I should be focusing on the things that make me who I want to be, and not the things that I think will raise me in the esteem of others. That being said, it turns out that these are often the same things! In my blinkered past, I could only imagine people being judged based on income or job title and never thought of people being judged by the quality of life they lived. Or, I never imagined that there were other ways to judge quality of life than through financial and career success. 

 I know, I know, there are tons of after school specials that explain this stuff, but for whatever reason it took me four decades before I finally started picking up what they were putting down. All of which is to say that I have spent a lot of my recent years checking boxes off of someone else's bucket list without ever thinking about if it is what I am supposed to be doing. On a macro scale, my life is moving in the right direction, my kids are healthy, I have a good job that I think I am good at, I am finishing a terminal degree in a subject that I am strongly interested in, and I think that I am working toward making the world a better place. On a micro level, though, a lot of this building towards the future caused me to cast aside things that I enjoyed but couldn't quantify the value of, if that makes sense. Of course, blaming all of this on a lack of self reflection is kind of ignoring the fact that there are lots of things we do as adults because we have to, and I didn't really have much choice in my lack of free time due to work and family. Still, my kids are young but getting a bit more independent, I am fairly entrenched at work, and this should be my last semester as a student (knock on wood). All of this means that I need to start reprioritizing and figuring out what it is I want to be doing, rather than focusing on what I have to be doing. 

Chief among the things that I would like to start reinvesting my time into are coding and blogging. Neither are related to my job or anything like that, but I enjoy both while being good at neither. So all this navel gazing and rambling is basically to say that I am hoping that I will start both blogging and coding with some regularity going forward. Indeed, I just published a fifteen minute incremental game called Snail Facts! (go check it out, I'll wait), and am working on a homepage redesign to reflect my current style sensibilities. I finished the desktop version, more or less, but now I need to figure out how to translate that aesthetic to work on a phone screen. Still thinking about it. Anyway, until later, yo.

Wednesday, January 2, 2019

Check us out on itch.io!

Happy New Year! We have started porting our Android games over to itch.io 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:

/home/netbook/AndroidStudioProjects/dotsdots/android/assets


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;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

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

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

@Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();
elapsedTime += Gdx.graphics.getDeltaTime();
batch.draw(animation.getKeyFrame(elapsedTime, true), 0, 0);
batch.end();
}

@Override
public void dispose () {
batch.dispose();
textureAtlas.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 += Gdx.graphics.getDeltaTime();
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,
(textureAtlas.findRegion("0011")),
(textureAtlas.findRegion("0012")),
(textureAtlas.findRegion("0013")),
(textureAtlas.findRegion("0014")),
(textureAtlas.findRegion("0015")),
(textureAtlas.findRegion("0016")),
(textureAtlas.findRegion("0017")),
(textureAtlas.findRegion("0018")),
(textureAtlas.findRegion("0019")),
(textureAtlas.findRegion("0020")));
}
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 com.badlogic.gdx.tools.texturepacker.TexturePacker [inputDir] [outputDir] [packFileName]

// WINDOWS java -cp runnable-texturepacker.jar com.badlogic.gdx.tools.texturepacker.TexturePacker [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 com.badlogic.gdx.tools.texturepacker.TexturePacker '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.

Android:

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 'gradle-wrapper.properties' file under the 'Gradle Scripts' heading in the Project window.

We want to change the distributionURL line to:
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
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 'com.android.tools.build:gradle:2.3.3'
3. In the same file, under 'repositories' remove:
google()
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'

Desktop: 

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:
desktop:dist

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.

HTML:

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:
    /home/netbook/AndroidStudioProjects/dotsdots
    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.

Sunday, April 15, 2018

How Exactly Do I Start Android Programming?

There are two main things you need to begin to learn how to code. The first is practical knowledge, what language to learn, what sort of SDK (software development kit) to use, where to go for help, etc. The second, which I would argue is more important, is motivation. If you have an idea for a project that you want to build, learning to program will be much easier. While it is probably a good idea to start with a simple project, if your dream project is something large and complicated you can still break it down into bite sized chunks.

As for practical knowledge, I mentioned previously that I started by doing the Oracle Java Tutorials and didn't feel that they were helpful in learning about Android programming. However, after sleeping on it, I think that by following those tutorials it 'primed the pump' as it were and helped me understanding all the stuff I learned later.

Anyway, let's do this in list format so it is a bit easier to follow:


  1. Have an idea - before you start it is a good idea to have at least a general idea of what kind of project you want to design. This will help with motivation and guide your learning so you can complete the project. It doesn't need to be a detailed road map, in fact I think it is better to keep your idea flexible so that it can change as your knowledge grows. For example, I have ideas for a lot of projects that turn out to be completely infeasible, but with a flexible mentality they often turn into other projects that are possible for me to complete.
  2. Oracle Java Tutorials - Take a look at the first three to five beginner tutorials here. There is really no need to go further than that because they don't apply to Android development, but definitely the first three will be a great primer on how everything works. Particularly the second tutorial will be useful for people who are just starting out.
  3. Install Android Studio - Now it is time to start the actual task of development. Download Android Studio, install it and get ready.
  4. Use Android Tutorial - Check out the early developer guides provided at developer.android.com. These get pretty in depth, but if you go through just the first couple of them that will give you an idea of how Android development works.
    1. Android Studio can compile native C code as well as Kotlin and Java, but I recommend sticking to Java for the time being because there are a huge number of resources for using Java in Android development and that will come in handy as you learn.
  5. Fool Around - Now you should have an extremely rudimentary idea of how to develop a basic Android app. Try things out on your own. Add pictures and text, add links, try to change things programmatically, try to implement some code related to your app idea. A lot of this will not work, and that's OK. You can keep trying things and testing ideas, and it will give you a good idea what you want to learn and what direction you want to take your app idea in.
  6. Search Stack Overflow - This is the single most helpful thing you can do as a beginner Android developer. Once you have figured out what you want to do and have realized that you don't know how to do it, it is a great time to go look at Stack Overflow. Nearly every question under the sun has already been asked and answered with code samples and explanations on how everything works. 
    1. In addition to looking at the code in the answers provided, it is good to look at the code provided in the questions because we can see the kinds of problems people are running into. This will help us avoid these problems in the future.
    2. It is ok if you don't understand what the code means right away. Some of the stuff is more complicated than others, and there is definitely going to be code that is opaque to you.  This is fine, because a nice  thing about Stack Overflow is that people leave explanations in addition to code samples. Follow along as best you can.
    3. Don't be afraid to copy and paste code fragments into your own code and try to make it work. This is a great way to learn and it can help you figure things out on your own.
  7. BACK UP YOUR CODE - Once you start making simple apps it is a good idea to open an account at Github or Bitbucket to keep your code backed up.  Both are fine, and there are other options out there, but I personally use Bitbucket because it allows you to keep your code private (Github does this with a paid tier, but on Bitbucket you can do it for free). This might not be a big deal to you, but I am a little bit ashamed of my code, so I don't want others to see it.
  8. Sign up for a Google Play Developer Account - Once you have an app you feel ready to release, go over to the Google Play Developer page and sign up. Pay the $25 for a lifetime account, and get ready to publish your app!
  9. Release your app through Alpha or Beta channels first - When you go to release your first app, you might feel like it is a good idea to release to production immediately. Hold your horses! If you turn on pre-launch reports (it is in the menu on the left of the Play Developer Console page, under 'Release Management') and upload the app to Alpha or Beta, the app will be briefly tested on a variety of devices. This has saved my bacon on several occasions where I forgot something simple (like switching from test ads to live ads or a weird crash that occurred from the soundpool that I didn't notice because I had sound off) and it causes crashes on the test devices. 
  10. Pop open the champagne, you have an app in the Play Store!

This is a very brief overview of the basic steps that I followed to start Android app development, but I think they might be helpful to some others that feel like they don't know where to start. Over the next few posts I will dive into some of the steps in a bit more detail, and will discuss some of the hurdles that I faced in the very beginning.

Tuesday, April 10, 2018

Why Should Beginners Start with Android Development?

The main reason I decided to make Android apps rather than iPhone apps is because I have an Android phone (makes sense, right?), but there are other pragmatic reasons that make Android more appealing to hobbyist developers like myself.

First of all, to post your apps in the Google Play Store you have to pay a developer fee of 25 US dollars. This is a one time fee and once paid it allows you to post as many apps as you would like to the Google Play Store. Conversely, to post apps to the Apple app store, you have to pay a fee of 99 US dollars every year. While this isn't a big deal for larger developers, it is pretty unlikely for a hobbyist to make any significant money so a lower fee is going to be more comfortable.

While developing for the Apple app store might be slightly easier (fewer devices and screen sizes lead to less possible issues, Android's Java is notoriously bad at memory management, among other things), to a novice developer there won't be much difference at first. Also, this minor benefit is greatly outweighed by the ease of publishing on Android. Both app stores nominally review all apps that are posted, but Android has a much more lax set of standards which are easier for beginners (like me) to meet. This is good because as design novices it is very unlikely for us to create something amazing in our first go around and being able to see your app in the Play Store is much more motivation to continue compared to receiving a rejection letter from Apple.

Also, the Apple App Store has a policy of removing older, un-updated apps. While this is a reasonable policy, if you are creating apps as a hobby after your kids go to bed (like me!), it is a hassle to maintain all of your previous apps to ensure they meet future guidelines.

For these reasons, I think it is better to start out creating with Android. It is cheaper, it is easier to remain motivated, and your apps are likely to remain available longer.

A Journey of a Thousand Miles Begins with a Single Step

So a couple years ago I used to do Amazon Mechanical Turk to pass the time. I didn't really need the money, but it was fun (for some value of 'fun') and earned me a few spare dollars on the side. I never got super into it, but would just randomly do tasks that piqued my interest, and as such wasn't exactly efficient. At the same time, I wasn't really doing it for the money, so it didn't really matter.

Mechanical Turk is how I got interested in coding, though. One day I saw a long term job for like $10 or something (this was in 2016, so I am not totally sure) to test a Python teaching site. Aside from typing in lines of BASIC from the back of old computer magazines and doing some very, very basic coding in the same, I had no real experience with that side of things. At the same time, it was something I had been curious about and this spurred me to check it out. Plus, they would pay me to do it (sure, it was only like ten bucks, but why not?).*

After spending a few days going through the Python course I started thinking about how I could apply this to my own life, and decided that I wanted to try my hand at making Android apps. Knowing nothing about Android, I did a quick Googling and saw that most Android apps were created using Java. I then Googled how to learn Java and found the Oracle site, which had plenty of tutorials and documentation.

What I didn't realize at the time was that regular Java and Android Java were not exactly the same thing. I think doing those tutorials helped me grasp some basic concepts about object oriented programming and how everything fit together, so it was probably worthwhile, but had I known that they weren't directly related I might have skipped the Oracle stuff. Of course it is hard to tell how much it actually helped me, and I only spent a short time there, so it doesn't really matter much.

Next, I wanted to learn about how to put Android apps together. After a couple false starts, I ended up downloading Android Studio and from there began my incredibly successful and lucrative** app career.

Ok, the past two posts have briefly explained where I am coming from, and now the following posts will be a bit more pragmatic in nature so that they can hopefully help people like me who are just getting started. Until then, be cool and try to do something nice for a neighbor.


*I went back through my old emails and found the site but it is no longer active, which is unfortunate because I kind of want to reach out to the creator know that they at least helped me out. But I digress.

**this part is not true. 

Monday, April 9, 2018

Frist Post

So blogging is dead, but I have recently begun learning Android app design and wanted to kind of chronicle my progress. Unfortunately I might have waited a little bit too long because I already have six apps in the app store.

None of them are very complicated (or popular), and I think I only released my first app about a year ago (I just checked, it was about 18 months ago), though, so I am still very much a beginner.

One of the main reasons that I want to write about stuff here is that this is just a hobby to me. I am a university professor (totally unrelated field) and students are all under the impression that they can become zillionaire app developers or Youtubers or whatever. I would like to be able to point them somewhere that shows how making even a simple app is a ton of hard work and even if the app is perfect (as all of mine are ;)) that is no guarantee that anyone will download them.

Anyway, because of my job, I am lucky enough to have free time to do this as a hobby, but I also have three young kids so it isn't like I have hours and hours a day to spend coding and doing stuff. My main hope is that I can dissuade people who think that app making is a get rich quick scheme, and conversely I can hopefully help people who want to learn a bit about coding but are kind of scared and don't know where to start. To that end, my next post will discuss how and why I ended up designing Android apps. Until then, have a nice day and try to be kind.