Understanding the build environment and project structure
Once the gdx-setup tool is finished generating the project files for us, we can look at the general structure to get a better idea of the project layout. In order to understand why certain files are in the project and how third-party dependencies are handled, we will need an overview of Gradle, the dependency management and build system that LibGDX currently uses.
Why Gradle?
In the beginning, the only build tool available for Java projects was Make. Projects quickly became unmanageable as the requirements and dependencies exploded along with the popularity of the language. Around the year 2000, Ant came to the rescue with its control of the build process and its low learning curve with much more readable build scripts. As great as Ant's procedural programming methodology was for creating scripts, it proved difficult to maintain in part because the XML-based script files tended to grow in complexity and verbosity. In 2004, Maven came along to address the issues with Ant and improve upon it with its simplicity. Dependency management was Maven's goal with a design that regards all projects as having a specific structure, a set of supported task workflows, and the ability to download dependencies over the network.
Maven didn't come without its own host of problems, including the inability to correctly manage conflicts between different versions of the same library, and the difficulty for someone to create customized build scripts because the scripts didn't exactly fit Maven's rigid structure.
In 2012, Gradle came along and built upon the concepts of both Ant and Maven to get a build tool that represents the best of both systems. First, Gradle uses a domain specific language (DSL) based on Groovy instead of the XML-based build scripts. This removes a lot of the verbosity that we had with XML build scripts, leading to shorter and clearer scripts. Also, under the covers, Gradle creates a directed acyclic graph to determine the order in which tasks can run, removing the rigidity of Maven's lifecycle and the complexity of Ant's dependency with partial ordering.
Benefits of Gradle
What is one benefit of using Gradle with LibGDX? Well, before Gradle support was added, all the LibGDX source, release, and native JAR files would live as part of the project hierarchy. This was a problem because LibGDX essentially polluted the source control system, testing the patience of whoever had to update to a later version of LibGDX in order to get one bug fix. Gradle fixes these problems because now LibGDX and all its dependencies live outside your project. If you want to test your game build against a different version of LibGDX (or any of the other dependencies), it is as easy as changing the build version number in the build.gradle
file in the root directory of your project. When you run the next build, Gradle will pull in the updated libraries that you specified from a central repository and then store them.
What if you missed a dependency when using the gdx-setup tool? All you need to do is add the dependency declarations to your build.gradle
file in your project's root directory. The dependency declarations adhere to the following convention:
compile '<groupId>:<artifactId>:<version>:<classifier>'
You can search for third-party extension declarations at http://github.com/libgdx/libgdx/wiki/Dependency-management-with-Gradle. After updating your build.gradle
file and rebuilding, you will now have the dependencies as part of your project.
Project structure
On Windows, if we open up a Command Prompt in the target directory where the gdx-setup tool outputs our project, we can get a better idea of the project structure with the following command:
C:\BludBourne>tree /F /A
The output will be something similar to the following (numbers were added for an easier reference):
C:. 1)| .gitignore 2)| BludBourne.iml 3)| BludBourne.ipr 4)| BludBourne.iws 5)| build.gradle 6)| gradle.properties 7)| gradlew 8)| gradlew.bat 9)| settings.gradle | +---core 10)| | build.gradle 11)| | core.iml | | 12) +---assets | | badlogic.jpg | | | \---src | \---com | \---packtpub | \---libgdx | \---bludbourne 13)| BludBourne.java | +---desktop 14)| | build.gradle 15)| | desktop.iml | | | \---src | \---com | \---packtpub | \---libgdx | \---bludbourne | \---desktop 16)| DesktopLauncher.java | \---gradle \---wrapper 17) gradle-wrapper.jar 18) gradle-wrapper.properties
This project structure is the initial project generated with gdx-setup for the reference RPG for this book, called BludBourne, and is described as follows:
.gitignore
(1): This is a convenience file used by the source control system, Git. Specifically, this file specifies the untracked (not under source control yet) files to ignore. These would include files such as build output and temporary files.BludBourne.iml
(2): This file type is the project configuration information for modules stored as part of the IntelliJ IDEA project. For instance, the initial module will be a Java module that contains all the functionality to build Java projects.BludBourne.ipr
(3): This file type is the core project information and setting for IntelliJ IDEA projects. This would include items such as project paths, compiler options, and Javadoc generation settings. This file is also the launch file type associated with IDEA.BludBourne.iws
(4): This file type stores your personal workspace settings for IntelliJ IDEA projects. It is recommended that this file is not checked into your source control system.build.gradle
(5): This is the primary Gradle build file. It defines all dependencies and plugins to use in your build environment.gradle.properties
(6): These are settings used to configure your Java build environment. This would include items such as JVM memory settings and setting the Java home (path to JDK).gradlew
(7): This file is the Gradle startup script for Unix-based systems.gradlew.bat
(8): This file is the Gradle startup script for Windows. You can pass command-line operations as well, including the following commands to get information about projects:gradlew -q projects
And:
gradlew core:tasks
settings.gradle
(9): This file defines all of the submodules for your project. These are the subprojects that you defined in gdx-setup, includingcore
.core/build.gradle
(10): This is a Gradle build file specific to this submodule. In general, you will not need to update these submodule configuration files.core/core.iml
(11): This is a configuration file for modules stored as part of the IntelliJ IDEA project for this subproject. The information will include items such as paths to the LibGDX libraries.core/assets
(12): This is the directory where you will store all of your game assets such as bitmaps, sprites, sound, music, and maps for the desktop.BludBourne.java
(13): This is the starter class that is autogenerated for theBludBourne
project with the gdx-setup tool:package com.packtpub.libgdx.bludbourne; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class BludBourne extends ApplicationAdapter { SpriteBatch batch; Texture img; @Override public void create () { batch = new SpriteBatch(); img = new Texture("badlogic.jpg"); } @Override public void render () { Gdx.gl.glClearColor(1, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batch.begin(); batch.draw(img, 0, 0); batch.end(); } }
As we can see, the starter class
BludBourne.java
(whose instance was passed to the backend constructorLwjglApplication
inDesktopLauncher.java
) is a concrete implementation of theApplicationListener
interface (or in this case inherits from the abstract base classApplicationAdapter
, which in turn implements the interface with dummy stubs). This is also the location where your source files will live.desktop/build.gradle
(14): This is a Gradle build file specific to this submodule. In general, you will not need to update these submodule configuration files.desktop/desktop.iml
(15): This is a configuration file for modules stored as part of the IntelliJ IDEA project for this subproject. The information will include items such as paths to the LibGDX libraries.DesktopLauncher.java
(16): This is the only platform-specific class for the desktop. Inside this class, we can see how our game fits into the beginning of the LibGDX framework lifecycle:package com.packtpub.libgdx.bludbourne.desktop; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.packtpub.libgdx.bludbourne.BludBourne; public class DesktopLauncher { public static void main (String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); new LwjglApplication(new BludBourne(), config); } }
This autogenerated class implements the main entry point of our game and passes our starter class object,
BludBourne
, to the platform's backend implementation of theApplication
interface. The backend implementation of theApplication
interface for the desktop isLwjglApplication
, which is part of the LibGDX backend package for the desktop called LWJGL (com.badlogic.gdx.backends.lwjgl
).LWJGL, an abbreviation for Lightweight Java Game Library, is a Java-based open source game development library for accessing hardware resources on the desktop. The driving philosophy is to expose underlying technology as a thin wrapper in order to keep the API simple. LWJGL enables cross-platform (Windows, Mac OS X, and Linux) access to popular native APIs such as OpenGL for graphics and OpenAL for audio. As a side note, Minecraft was originally developed using LWJGL.
gradle-wrapper.jar
(17): This is the main binary for Gradle execution on the desktop that is included in the classpath in thegradlew.bat
file.gradle-wrapper.properties
(18): These properties define the version of Gradle to fetch and install.
Version control systems
I highly recommend that you take a look at a version control system (VCS) and if you have not used one in the past, take some time in ramping up with how to use one. Nothing is worse than to make one small tweak to your game in a late hour before a demo and all of the sudden, you find yourself with some game objects passing through each other and you have no idea what changed. VCS systems also help manage future content updates, such as patch releases and downloadable content (DLC) for your game. They help you to clearly identify where changes were made and what areas need to be tested, giving you better management over your deadlines by eliminating the guess work.
The role of version control systems is definitely a must in order to have an audit record of all changes made, and a mechanism to look at differences in the file versions to find these subtle bugs. Today, this doesn't even have to affect your budget for your game, as individual indie developers or small teams can usually use these VCS solutions for free.
The following are some VCS solutions available today:
- Mercurial: This is a free, distributed source control management tool (http://mercurial.selenic.com/)
- Perforce: This is a commercial, proprietary revision control system. Perforce is free for up to 20 users, 20 workspaces, and unlimited files (http://www.perforce.com/)
- Subversion: This is a software versioning and revision control system distributed as free software under the Apache License (http://subversion.apache.org/)
- Git: This is a free, distributed revision control system (http://git-scm.com/)
I have used many different types of VCS solutions throughout my career, ranging from legacy, bloated, expensive ones, to free ones with limited features. I have found Git to be easy to learn (once you ignore old source code repository models such as a central host server) and very fast. I personally recommend Git, and I will be using it for the BludBourne project. There is a host of information available on how to use Git, but I found the book Pro Git, by Scott Chacon and Ben Straub, most useful for quickly getting up to speed on Git (it is available for free at http://git-scm.com/book/en/v2).
You can use Git from the command line, but for my purposes, I prefer GUI clients so that I can see the differences between different check-ins and the history of particular files more clearly. There are many different types of GUI clients available; most are listed at http://git-scm.com/download/gui/linux. Some of them are as follows:
- GitHub for Windows: This is free and can be found at http://windows.github.com/
- SmartGit: This is $79 per user or free for non-commercial use
I have personally found SmartGit easy to use, fast, and actively maintained. For the BludBourne project, I will be using SmartGit as my Git client of choice.
I recommend that once you generate your project using the gdx-setup tool, you can create a Git repository at the root project directory and then commit those changes to your local master branch. This will allow you to make changes as you progress through this book, and not worry about breaking your project.