docsReading time: 5 minutes

These are wip notes for the documentation

TODO: Deployment

How to relase your game


Update version

  • Increment the build of the game (e.g. v1.0.1 to v1.0.2)
  • Update version build in (or whatever your Main class is called)
  • Update version build build.gradle
    • Update .exe version in launch4j configuration group
  • Commit the change

Create new release draft on github

  • Go to your repository's releases page
  • List all the changes that have been made to the game here
    • Closed issues
    • Check all commits since last build
    • This is crucial since the text will be reused for patch notes on different platforms

Build with Gradle

Build automation is a blessing! Let's have a look at how to build and deploy your game using Gradle.
To build Windows executables, we are going to use the launch4j plugin. We set up different Gradle tasks for each target platform as well.

Your project's build.gradle should look something like this:

plugins {
  id '' version '2.4.4'

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'maven'

archivesBaseName = "mygame"
version = "v1.0.2"
targetCompatibility = "1.8.0"

sourceSets { "src" "resources" "sounds" "maps" "localization"

  main.resources.includes = ["game.litidata"]

repositories {

dependencies {
 compile project(':litiengine')

compileJava.options.encoding = 'UTF-8'

jar {
  from {
    configurations.runtime.collect {
      it.isDirectory() ? it : zipTree(it)
    configurations.compile.collect {
      it.isDirectory() ? it : zipTree(it)
  }  {
     exclude 'META-INF/services/**'

  // make sure to only include service providers from the litiengine when directly referencing the project
  from ("${project(':litiengine').projectDir}/resources/") {
    include 'META-INF/services/**'

    include '**/*' 
    exclude 'sprites/*'

  from('sounds') { include '**/*' }
  exclude '**/*.dll'
  exclude '**/*.jnilib'
  exclude '**/*.dylib'
  exclude '**/*.so'
  exclude 'junit**/**'

  from 'game.litidata'

  manifest {
    attributes 'Class-Path': ".",
               'Main-Class': "de.gurkenlabs.mygame.MyGame"

launch4j {
  mainClassName = 'de.gurkenlabs.mygame.MyGame'
  icon = 'icon.ico'
  outputDir = 'libs'
  outfile = archivesBaseName +'.exe'
  companyName = ''
  version = '1.0.2'
  textVersion = '1.0.2'
  copyright = '2020'
  bundledJrePath = 'jre'
  jvmOptions = ['-Xms256m', '-Xmx1024m']
  cmdLine = '-release'

task copyNativeLibs(type: Copy) { 
  def litiengineLibs ='../litiengine/build/libs'
  def buildFolder = new File(buildDir, 'libs')

  from(litiengineLibs) { 
   include '**/*'
   exclude '**/*.jar'
   exclude '**/*.zip'
   exclude 'LICENSE'
   exclude 'lib/**'

    include 'icon.ico'
    include ''
    include 'steam_appid.txt'
    include 'jre/**'

  into buildFolder

build.dependsOn copyNativeLibs

task distZipWindow(type: Zip) {
   group 'build'
   from 'build/libs/'
   include '*.exe'
   include '*.dll'
   include ''
   include 'jre/**'

   archiveName archivesBaseName + '-' + version + ''
   exclude archiveName
   exclude 'jinput-dx8_64.dll'
   exclude 'jinput-raw_64.dll'
   exclude 'steam_api64.dll'
   exclude 'steamworks4j64.dll'

task distZipLinux(type: Zip) {
   group 'build'
   from 'build/libs/'
   include '*.jar'
   include '*.so'
   include ''

   archiveName archivesBaseName + '-' + version + ''
   exclude archiveName

task distZipOSX(type: Zip) {
   group 'build'
   from 'build/libs/'
   include '*.jar'
   include '*.jnilib'
   include '*.dylib'

   include ''

   archiveName archivesBaseName + '-' + version + ''
   exclude archiveName

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
  • Disable debug settings in the
  • Set Game.DEBUG = false in before building anything that is released
  • Execute the following Gradle tasks your game project (order matters)
    • clear
    • fullbuild
    • build
    • createAllExecutables
    • distZipWindow, distZipLinux, distZipOSX
  • There should now be three archive files, one for each target platform: mygame\build\libs\ mygame\build\libs\ mygame\build\libs\
    • Make sure that they contain the jre folder, the jinput and steamworks x86 native assemblies, the file (and the mygame.exe executable in the Windows archive).
    • These are the archives you are going to deploy to the players.


  • Before deployment, we should quickly check if the game runs properly
  • Copy the archive somewhere (Desktop), extract it and run the executable
  • Ideally: Copy it to an empty VM instance (e.g. a freshly created Windows 7) and see if it runs



  • Upload created archive to the github release draft
  • Polish the release description
  • Publish the release


  • Login to
  • Select "MyGame" App and go to Edit Steamworks Settings/Steampipe/Builds
  • Since "MyGame" is probably < 256MB, we can usually directly upload it here.
  • Upload new build
    • Describe it with something like "Update to version 1.X.X" so that we can later on identify what happend in that build by the patchnotes
  • Set the build live on the development and default branches
  • Update the game from Steam (might need to restart the client) and see if it runs properly

  • Edit your Game page
  • Scroll down to Uploads
  • Click Upload files and select the archive
  • Select "Executable" for "Windows"
  • Disable the old build for download and set the new one as default


Post the patch notes

  • Possible headline: Patch 1.X.X is live now!
  • Create new patchnotes image
  • Post patchnotes as new announcement on Steam Community{mygameid}/announcements/create/
    • Make sure to check "Tag as Patch Notes"
    • Link it in
    • twitter
    • fb
    • reddit/r/IndieGames/
    • instagram
    • tumblr
  • Post patchnotes as new devlog on{mygameid}/devlog

steffen-wilkeLast updated 2 years ago
On this page