Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LibGDX without Eclipse or Ant

Tags:

android

libgdx

Background

So lately I wanted to build a game for Android and started looking around for a good library to help with that. LibGDX hit all the right checkboxes. But as per usual ( and understandably so ) all the documentation only mentioned using Eclipse with ADT. Previously, I used Ant to build my Android projects so I assumed I could use that but learning Ant, useful though it may be, seemed a bit much considering surely there couldn't be that many commands to build the project?

Question

So what steps do I need to do create, compile and run a LibGDX project that targets at least the desktop and Android platforms without using Eclipse, Ant, or some other IDE/build tool?

I am going to answer my own question but the methods I use to create the final product may not be the best so criticism is welcome.

like image 961
jmathew Avatar asked Dec 29 '12 07:12

jmathew


People also ask

Do you need Android studio for LibGDX?

Setting the Project Up If you want to work on the code of libGDX itself, you need to get it set up on your local machine. For this, Android Studio is strongly recommended as IDE!


1 Answers

The following is taken from a project on github I made which has all the code and info.

PaperPlanes

This is a simple application to test out libgdx development without using Eclipse or Ant to build the project. Primary focus is on integrating libgdx with my Ant-less, commandline only, development environment.

The Process

I am going to go through, from start to getting a runnable build, a simple project that will incorporate the knowledge I've gathered researching how to setup a libgdx project without using Ant or Eclipse. The general process is straight forward in hindsight, but I'm writing this because I struggled with finding answers online, specifically for targeting the android build.

For the purposes of this guide the project name will be PaperPlanes just because its better than typing 'TestGameLibGdx'. The project code will consist of moving a loaded texture to a clicked/touched point. The app itself is largely irrelevant, just saves someone the step of finding some code to test the steps I used.

I assume that the environment is already set up to build and deploy android applications with Ant or Eclipse. Currently you will also need java 1.6 because there seems to be some problems using 1.7 and compiling for android.

Make Directory Structure

First thing is to make folders for the different targets as per usual when using libgdx. We will be dealing with each folder indivdually later on. I do not have a directory for iOS or HTML5 targets as I haven't tried to build those yet.

mkdir -v PaperPlanes
cd PaperPlanes
mkdir -v main desktop android assets

Setup Main directory

This is where the bulk of the code will go.

cd main
mkdir -pv libs src/com/jeff/paperplanes 

Setup Desktop directory

Pretty straight forward, same as main but with a bin directory.

cd desktop
mkdir -pv bin/classes libs src/com/jeff/bucket 

Setup Android directory

We'll build the android directory with the skelton project generated by the android tool. Alternatively, you could create the directory structure yourself by following the guide provided in the sources section. Mind the --target and --path flags as they are specific to your setup.

cd android
android create project --target 1 --name PaperPlanes --path /home/jeff/playground/PaperPlanes/android --activity PaperPlanesActivity --package com.jeff.paperplanes
mkdir -pv bin/classes bin/lib

Remove the files we don't need. I removed progaurd files as this project has no need for it.

rm build.xml local.properties project.properties ant.properties proguard-project.txt

Aquire libgdx library files

Download the libgdx nightly and put the libs you need in the relevant directories. The snippet below is how I update my libraries.

LIBGDX_ZIP="libgdx-nightly-latest.zip"
wget http://libgdx.badlogicgames.com/nightlies/$LIBGDX_ZIP

unzip -o $LIBGDX_ZIP gdx.jar gdx-natives.jar gdx-backend-android.jar gdx-backend-lwjgl.jar gdx-backend-lwjgl-natives.jar extensions/gdx-tools.jar 'armeabi/*' 'armeabi-v7a/*'
rm -v $LIBGDX_ZIP

mv -v gdx.jar main/libs/
cp -Rv extensions main/libs
mv -v gdx-natives.jar gdx-backend-lwjgl.jar gdx-backend-lwjgl-natives.jar  desktop/libs/
mv -v gdx-backend-android.jar android/libs/
cp -Rv armeabi-v7a armeabi android/libs/

rm -rf extensions armeabi armeabi-v7a

The apk needs to include the areabi* directories when installed. So make some links inside bin/lib directory to those folders. You could also just copy over the actual folder, but libs go in the libs directory dammit!

cd android/bin/lib
ln -s ../../libs/armeabi
ln -s ../../libs/armeabi-v7a

Get some assets

Assets are strange when sharing with an Android application.

The desktop application looks for assests starting in the root directory of the application so you'd refer to an asset like so:

Gdx.files.internal( "assets/plane.png" )

However, the android application looks for assets starting in the assets directory. Thus the above code would cause it to look for a file in a folder ROOT/assets/assets/plane.png.

So we can either scatter all the assets in the root directory or just create a link to the ROOT/assets folder within ROOT/android/bin/assets/. It looks stupid but makes asset references consistent accross the platforms.

I'm sure there's a better way to do this, but it works.

Anyway, this app only uses one texture called assets/plane.png.

Write some code

You can find plenty of examples in the libgdx repository. Below I will dump the code I used to test this guide as I wrote it.

main/src/.../PaperPlanesGame.java

package com.jeff.paperplanes;

import com.badlogic.gdx.Game;


public class PaperPlanesGame extends Game {
  private MainScreen ms; 

  @Override
  public void create() {
    ms = new MainScreen( this );
    this.setScreen( ms );
  }
}

main/src/.../MainScreen.java

package com.jeff.paperplanes;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.Screen;

public class MainScreen implements Screen {

  PaperPlanesGame g;
  Texture planeImage;
  Rectangle planeRect;
  SpriteBatch spb;
  Vector3 touchPos;
  OrthographicCamera cam;

  public MainScreen( PaperPlanesGame g ) {
    this.g = g;

    // load assets
    planeImage = new Texture( Gdx.files.internal( "assets/plane.png" ) );

    // initialize rectangle
    planeRect = new Rectangle();

    // initialize spritebatch for drawing
    spb = new SpriteBatch();    

    // initialize our camera
    cam = new OrthographicCamera();
    cam.setToOrtho( false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
    cam.update( true );

    // touch location
    touchPos = new Vector3();

  }

  @Override
  public void show() {
  }
  @Override
  public void render( float delta ) {
    // clear screen
    Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );

    // update camera
    cam.update();


    // begin draw
    spb.setProjectionMatrix( cam.combined );
    spb.begin();

    // move our plane and center it
    spb.draw( planeImage, planeRect.x - ( planeImage.getWidth() / 2 ) , planeRect.y - ( planeImage.getHeight() / 2 ) );
    //spb.draw( planeImage, planeRect.x, planeRect.y );
    spb.end();

    // update touch position
    if( Gdx.input.isTouched() ) {
      touchPos.set( Gdx.input.getX(), Gdx.input.getY(), 0 );

      // only unproject if screen is touched duh!
      cam.unproject( touchPos );

      // converts the coord system of the touch units ( origin top left ) to camera coord ( origin bottom left )
      planeRect.x = touchPos.x;
      planeRect.y = touchPos.y;
    }

    Gdx.app.log( "X + Y", planeRect.x + " + " + planeRect.y );

  }

  @Override
  public void resize( int width, int height ) {
  }
  @Override
  public void hide() {
  }
  @Override
  public void pause() {
  }
  @Override
  public void resume() {
  }
  @Override
  public void dispose() {
  }
}

android/src/.../PaperPlanesActivity.java

package com.jeff.paperplanes;

import android.app.Activity;
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;

public class PaperPlanesActivity extends AndroidApplication {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    AndroidApplicationConfiguration cf = new AndroidApplicationConfiguration();

    cf.useGL20 = true;
    cf.useAccelerometer = true;
    cf.useCompass = false;

    initialize( new PaperPlanesGame(), cf );
  }
}

desktop/src/.../PaperPlanesDesktop.java

package com.jeff.paperplanes;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

public class PaperPlanesDesktop {

  public static void main( String[] args ) {
    LwjglApplicationConfiguration cf = new LwjglApplicationConfiguration();
    cf.title = "PaperPlanes";
    cf.useGL20 = true;
    cf.width = 800;
    cf.height = 480;

    new LwjglApplication( new PaperPlanesGame(), cf );
  } 
}

Remember when dealing with the android target to review AndroidManifest.xml.

Compile for Desktop

This is the easy bit. We are running the compile command from the ROOT directory.

# Compile
javac -verbose -classpath "desktop/libs/*:main/libs/*:desktop/bin/classes" -sourcepath desktop/src/com/jeff/paperplanes:main/src/com/jeff/paperplanes -d desktop/bin/classes desktop/src/com/jeff/paperplanes/*.java main/src/com/jeff/paperplanes/*.java 

# Run
java -classpath "desktop/libs/*:main/libs/*:desktop/bin/classes" com.jeff.paperplanes.PaperPlanesDesktop

Compile Android

A bit more complicated than desktop. I am largely cribbing off of the work done by this guy. That guide is really helpful and worth reading through for explanations of each of the steps I will go through below.

We are running commands from the android directory.

First we make R.java, I don't really use any assets that are in it because that beats the cross platform point, but it seems I can't remove it without getting an error at runtime.

aapt package -v -f -m -M AndroidManifest.xml -I /opt/android-sdk/platforms/android-10/android.jar -S res -J src/ 

Now we compile our souce files. Note the -classpath make sure it lines up with where your libraries are.

javac -verbose -d bin/classes -classpath "bin/classes:/opt/android-sdk/platforms/android-10/android.jar:bin/lib/*:../main/libs/*:libs/*" -target 1.6 `find ./src -iname "*.java"` `find ../main/src -iname "*.java"`

Then make the Dalvik bytecode. Include all the library files used in the code.

dx --dex --output bin/classes.dex bin/classes libs/gdx-backend-android.jar ../main/libs/gdx.jar

Here we make our unsigned apk file.

aapt package -v -f -M AndroidManifest.xml -S res -I /opt/android-sdk/platforms/android-10/android.jar -F bin/paperplanes.unsigned.apk bin/ 

And then we sign it with a key.

jarsigner -verbose -keystore debugkey.keystore -storepass debug123 -keypass debug123 -signedjar bin/paperplanes.signed.apk bin/paperplanes.unsigned.apk debugkey

If you do not have a key you can generate one. Here's how to make one ( taken from the guide I've mentioned far too often ):

JAVA_HOME/bin/keytool
                -genkeypair
                -validity 10000
                -dname "CN=company name,
                        OU=organisational unit,
                        O=organisation,
                        L=location,
                        S=state,
                        C=country code"
                -keystore DEV_HOME/AndroidTest.keystore
                -storepass password
                -keypass password
                -alias AndroidTestKey
                -keyalg RSA
                -v

And finally we run zipalign and install it to the device.

zipalign -v -f 4 bin/paperplanes.signed.apk bin/paperplanes.apk

# First time install
adb -d install bin/paperplanes.apk

# Reinstall
adb -d install -r bin/paperplanes.apk

Sources

Building Android programs on the command line

An answer from SO that set me off

LibGDX github page

PaperPlanes (this project) github page

LibGDX API

LibGDX tutorial referenced when making the app

Another LibGDX tutorial referenced when making the app

like image 180
jmathew Avatar answered Sep 22 '22 06:09

jmathew