gui

Today, me and my partner at Educationally Designed released the fruit of over a month of development on Thyme. Thyme is an educational game to assist teenagers in time management and tracking, created as our final project for a grade 12 computer science class.

The premise behind Thyme is that the player will be given tasks to do, and for every task, they will need to estimate how long it would take them to do it. They then do said tasks and the game scores them based on how long it actually took them to do the task compared to how long they estimated it would take them.

There is a lot to be said about the philosophy behind our game, but today I will only be talking about the technical aspects of our development.

The GUI

We decided to use LibGDX’s Scene2d as our main GUI. This turned out to be a horrible decision at the beginning because it was extremely hard to learn. By the end of our development time, we had only learned the very basics of how GUI development works using Scene2d. However, we believe that the final product (that is, the aesthetic looks) were good.

Serialization

One of the things that we learned while creating Thyme was the ability to serialize objects in Java directly to a byte stream and then to a file. This allowed us to more easily store our game scores and read said scores back into Java objects without creating any parsers.

It was very simple to setup our scores to be serializable, since ArrayLists already implement the Serializable interface. We simply just made our own Score class implement serializable and that was all it took.

You can find the code to the backend of our scoreboard related classes here.

Data Parsing

Web Browser

In our game, we asked the user questions that they would find the answers to on our in-game web-browser, which read and parsed LML, a format designed to store Scene2d elements in an XML-like format. To create LML files, we first downloaded Wikipedia articles using their export tool and converted them to plain text using wikiextractor. I wrote a quick and dirty script that would take the output of wikiextractor and convert the paragraphs to LML, and added the title at the beginning. Although my script was quite simple, it did the job well and was able to process most articles with minimal problems.

The only other site that our web-browser was able to access was a fictional site called “randomfacts.com”. To get the random facts, we used an API to get raw JSON and converted it to LML using a similar method to my aforementioned script.

Reddit

(NOTE: None of the Reddit gifs are available in our source code on Github because they would be infringing on copyright.)

In one part of our game, we try to distract the user by randomly popping up a window with gifs and images obtained from Reddit. We downloaded these as videos and images from r/aww. We then used ffmpeg to convert the first 10 seconds of each video into the gif format. After, we compressed these gifs using the gifsicle tool. This reduced the size of our 50 gifs to around 200 megabytes, which was around 2x smaller than before compressing.

Lazy Loading

Because our gif assets were so large, we could not load all of the gifs at once. So instead, we created a lazy loader that would load gifs as you scrolled down on the Reddit window. This lazy loader also utilized threads as much as possible to prevent GUI hanging. To read and decode the gifs, we used a modified version of Gifdecoder, a library that decodes gifs and converts them into LibGDX Animations. This decoder mostly worked on a different thread, but needed access to the OpenGL thread to make textures. To offload as much work as possible to the loader threads, we further modified it by splitting the getAnimation method in twain, doing as much as possible in another method called prepAnimation. This reduced GUI hanging to as low as we could get it, and we are proud of the results.

You can see the modified source code here.

Travis CI

We used Travis CI during the development of Thyme to ensure that our pull requests properly built, before merging into the master branch. Travis was also used to automatically upload the resulting JAR file into our Github releases so we could have snapshots of the current state of our game. We found Travis extremely useful during development and we both will be using Travis in our future projects.

The End

While developing Thyme, me and my partner learned a lot about Java development, game development, git and so much more. But we also learned a lot about ourselves and our own development habits. This experience was invaluable and we will take what we have learned into the future, improving on our development skills and habits.

You can find the code of our project on Github.