Disclaimer
This series is a means for me to learn Kotlin. As such i might misuse some features of Kotlin, not follow best practices or simply to silly things. Please always check the comment section for feedback from more knowledgable people. I’ll also have follow up articles where i refactor the code to be more idiomatic. So, make sure to check back.
Why?
I recently started looking into alternative JVM languages. After a short interaction with Scala, i looked into JetBrains’ Kotlin. When learning a new language/platform, i usually write a simple application that allows me to iteratively explore new concepts and features. For my adventure in Kotlin i chose to write a Chip8 emulator.
My goals with this little series are as follows:
- Learn a bit of Kotlin
- Document my journey
- Get feddback from Kotlin users
- Show how to write a simple emulator
My non-goals are:
- Teach anyone Kotlin, use the official docs if you want to learn it all
- Write the most efficient and precise Chip8 emulator
Let’s get going.
Setting up a Kotlin project
As stated earlier, i’m not going to try and teach anyone Kotlin given my knowledge level. Instead i’ll comment on the tooling surrounding Kotlin. What i present may not be best practices but it’s what has worked for me.
The project i’m going to set up has to fulfil these requirements:
- Build management and packaging
- Dependency management
- IDE integration
- Version control
Requirements 1 and 2 can be achieved by choosing one or combining multiple of the following tools: Ant, Ivy, Maven, Gradle, SBT and so on. I’m going to use Gradle as there exists a first class Gradle plugin for Kotlin. It’s also quite a bit less verbose than Maven and hence suitable for a textual series like this.
Being a brain-child of JetBrains, Kotlin has first class support in Intellij IDEA, so that’s what i’m going to use. Quite a change for an Eclipse guy like me.
On the version control front i’m going to go with Git, hosting a repository on Github.
Given these choices, i need to install the following:
- Latest JDK (make sure the
bin/
folder is in your PATH) - A Git client (TortoiseGit on Windows, on Linux use your package manager, on Mac OS X use homebrew to get the latest and greatest)
- Intellij IDEA 13 (community edition will do)
- Gradle (make sure the
bin/
folder is in your path)
Project Structure, Build and Dependency Management
Let’s start by setting up a few folders and files for our project. We’ll add a build.gradle
file describing our Gradle build first:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.8.11' } } apply plugin: "kotlin" apply plugin: "java" repositories { mavenCentral() } dependencies { compile 'org.jetbrains.kotlin:kotlin-stdlib:0.8.11' } project.ext.mainClassName = "chip8.Chip8Package" task run(dependsOn: classes, type: JavaExec) { main = project.mainClassName classpath = sourceSets.main.runtimeClasspath standardInput = System.in ignoreExitValue = true } task dist(type: Jar) { from files(sourceSets.main.output.classesDir) from files(sourceSets.main.output.resourcesDir) from {configurations.compile.collect {zipTree(it)}} manifest { attributes 'Main-Class': project.mainClassName } } task wrapper(type: Wrapper) { gradleVersion = '2.1' } |
The buildscript
block is required to pull in the Kotlin Gradle plugin (line 6). Line 10 and 11 specify that this project uses both the Kotlin and Java plugin, allowing us to mix and match the two languages if required. Next we define the repositories from where dependencies are fetched. For now, the only required dependency is the Kotlin standard library (line 18). Finally i added two tasks (run
, dist
) to run the project and package it into a JAR for distribution. Note line 21 where i define the main class. That class name is used by the run
and dist
to execute our app and package our app as a runnable JAR respectively.
The wrapper
task pulls the Gradle wrapper files into our project structure. This will allow other people to work with the project without installing Gradle themselves.
The last missing bit is a source folder and main entry point. Per convention, the Kotlin source files are placed under src/main/kotlin
, Java source files are put into src/main/java
. Tests go into src/test/kotlin
and src/test/java
respectively. I put a very simple Hello-World style Kotlin app in src/main/kotlin/chip8/main.kt
:
1 2 3 4 5 |
package chip8; fun main(args: Array<String>) { println("Hello World") } |
Where is the Chip8Package
class we defined as the main class in the build.gradle
file? Turns out that Kotlin will put all top-level functions of a package into a synthetic class called <Packagename>Package
. We therefor have to specify that synthetic class for the JVM to run our main
function.
Before moving on, we’ll invoke the wrapper
task to pull the Gradle wrapper into our project:
1 |
chip8$ gradle wrapper |
The wrapper is composed of two script files (gradlew for *nix and gradlew.bat for Windows) and a folder called gradle/
which contains a tiny JAR and a properties file. From now on, we’ll invoke the script files (gradlew
, gradlew.bat
) in our project directory.
Running the app on the command line is as simple as calling the run
task:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
chip8$ ./gradlew run Downloading https://services.gradle.org/distributions/gradle-2.1-bin.zip ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. Unzipping /Users/badlogic/.gradle/wrapper/dists/gradle-2.1-bin/2pk0g2l49n2sbne636fhtlet6a/gradle-2.1-bin.zip to /Users/badlogic/.gradle/wrapper/dists/gradle-2.1-bin/2pk0g2l49n2sbne636fhtlet6a Set executable permissions for: /Users/badlogic/.gradle/wrapper/dists/gradle-2.1-bin/2pk0g2l49n2sbne636fhtlet6a/gradle-2.1/bin/gradle :compileKotlin warning:Annotations path entry points to a non-existent location: :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :run Hello World BUILD SUCCESSFUL Total time: 59.466 secs |
Note that we now use the gradlew
script instead of our local Gradle installation. The first time the wrapper is invoked, it downloads the Gradle version we specified in the wrapper
task and installs it. This may take some time but won’t be repeated on subsequent invocations.
We can also package our app as a runnable JAR via the dist
task and run that JAR:
1 2 |
chip8$ ./gradlew dist chip8$ java -jar build/libs/chip8.jar |
The project layout now looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
chip8/ build.gradle src/ main/ kotlin/ main.kt gradlew gradlew.bat gradle/ wrapper/ gradle-wrapper.jar gradle-wrapper.properties |
IDE Integration
Before we can import our project into Intellij IDEA, we need to install the IDEA Gradle plugin. Fire up IDEA, on the welcome screen go to Configure->Plugins
, click on Install JetBrains plugin
, search for Kotlin
and install the plugin.
We can now import the project by clicking on Open Project
on the welcome screen, navigating to the project folder and select the build.gradle
file. IDEA will ask us some specifics about our Gradle project. Make sure to select Use customizable gradle wrapper
, so IDEA uses our wrapper properly.

Once loaded, we can run our main function. The simplest way to do this is to open up the main.kt
file in IDEA, right click and select Run 'chip8.Chip8Package'
:

This will also create a configuration for us which we can use to launch and debug the app later on. Speaking of debugging, it works as you expect. Simply create a breakpoint in a source file in the line number margin on the left and start your app in debug mode:

Version Control
Time to push our master piece to Github. I created a Github repository called chip8 which you can follow along. Since we already have a folder, we can initialize the repository with a few magic incantations on the command line:
1 2 |
chip8$ git init chip8$ git remote add origin https://github.com/badlogic/chip8.git |
We should also create a .gitignore file so we don’t commit the build directory, IDEA project files and so forth:
1 2 3 4 5 6 |
.DS_STORE .idea/ .gradle/ build/ target/ *.iml |
Let’s add our initial set of files, commit and push them to the remote repository:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
chip8$ git add chip8$ git status On branch master Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: .gitignore new file: build.gradle new file: gradle/wrapper/gradle-wrapper.jar new file: gradle/wrapper/gradle-wrapper.properties new file: gradlew new file: gradlew.bat new file: src/main/kotlin/chip8/main.kt chip8$ git commit -m "initial commit" chip8$ git push -u origin master |
Let’s also tag this state:
1 2 |
chip8$ git tag -a part0 -m "part0" chip8$ git push --tags |
And we are done!
Up Next
You can now simply clone the repository and follow along the rest of the series, provided you installed all the tools we talked about earlier.
In the next article we’ll write a simple Chip8 ROM disassembler.
Following Along
- Install the required tools (JDK, IDEA, IDEA Kotlin plugin, Git)
- Clone the repo:
git clone https://github.com/badlogic/chip8.git
- Checkout the tag for the article you want to work with:
git checkout part0
- Import the project into IDEA (
Open Project, select build.gradle file, select "Use customizable gradle wrapper"
Happy coding!