在没有Eclipse或Ant的情况下使用LibGDX

jma*_*hew 5 android libgdx

背景

最近我想为Android构建一款游戏,并开始寻找一个好的图书馆来帮助解决这个问题.LibGDX点击了所有正确的复选框.但是按照惯例(并且可以这么理解),所有文档都只提到使用Eclipse和ADT.以前,我使用Ant来构建我的Android项目,所以我假设我可以使用它但是学习Ant虽然可能有用,但似乎有点考虑肯定没有那么多命令来构建项目?

那么我需要做什么步骤来创建,编译和运行至少针对桌面和Android平台的LibGDX项目,而不使用Eclipse,Ant或其他IDE /构建工具?

我将回答我自己的问题,但我用来创建最终产品的方法可能不是最好的,所以欢迎批评.

jma*_*hew 11

以下内容取自我所制作的github项目,其中包含所有代码和信息.

纸飞机

这是一个简单的应用程序,可以在不使用Eclipse或Ant构建项目的情况下测试libgdx开发.主要关注的是将libgdx与我的无Ant,仅限命令行的开发环境集成.

过程

从开始到获得可运行的构建,我将经历一个简单的项目,该项目将包含我收集的知识,研究如何在不使用Ant或Eclipse的情况下设置libgdx项目.事后的一般过程是直截了当的,但我写这篇文章是因为我努力寻找在线答案,特别是针对android构建.

出于本指南的目的,项目名称将是PaperPlanes,因为它比输入"TestGameLibGdx"更好.项目代码包括将加载的纹理移动到单击/触摸点.应用程序本身在很大程度上是无关紧要的,只是为了节省某人找到一些代码来测试我使用的步骤.

我假设环境已经设置为使用Ant或Eclipse构建和部署android应用程序.目前你还需要java 1.6,因为使用1.7和编译android时似乎存在一些问题.

制作目录结构

首先,在使用libgdx时,按照惯例为不同的目标创建文件夹.我们稍后将单独处理每个文件夹.我没有iOS或HTML5目标的目录,因为我还没有尝试构建这些目录.

mkdir -v PaperPlanes
cd PaperPlanes
mkdir -v main desktop android assets
Run Code Online (Sandbox Code Playgroud)

设置主目录

这是大部分代码的用武之地.

cd main
mkdir -pv libs src/com/jeff/paperplanes 
Run Code Online (Sandbox Code Playgroud)

设置桌面目录

非常直接,与主要相同,但有一个bin目录.

cd desktop
mkdir -pv bin/classes libs src/com/jeff/bucket 
Run Code Online (Sandbox Code Playgroud)

设置Android目录

我们将使用该android工具生成的skelton项目构建android目录.或者,您可以按照sources部分中提供的指南自己创建目录结构.注意--target--path标志,因为它们是您的设置特定的.

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
Run Code Online (Sandbox Code Playgroud)

删除我们不需要的文件.我删除了progaurd文件,因为这个项目不需要它.

rm build.xml local.properties project.properties ant.properties proguard-project.txt
Run Code Online (Sandbox Code Playgroud)

获取libgdx库文件

每晚下载libgdx并将所需的库放在相关目录中.下面的代码片段是我更新库的方式.

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
Run Code Online (Sandbox Code Playgroud)

apk需要areabi*在安装时包含目录.因此,在bin/lib目录中建立一些链接到这些文件夹.你也可以只复制实际的文件夹,但libs进入libs目录该死!

cd android/bin/lib
ln -s ../../libs/armeabi
ln -s ../../libs/armeabi-v7a
Run Code Online (Sandbox Code Playgroud)

获得一些资产

与Android应用程序共享时,资产很奇怪.

桌面应用程序从应用程序的根目录开始查找assests,因此您将引用如下资产:

Gdx.files.internal( "assets/plane.png" )
Run Code Online (Sandbox Code Playgroud)

但是,android应用程序会查找从assets目录开始的资产.因此,上面的代码将导致它在文件夹中查找文件ROOT/assets/assets/plane.png.

因此,我们可以将所有资产分散到根目录中,也可以只创建指向该ROOT/assets文件夹的链接ROOT/android/bin/assets/.它看起来很愚蠢,但使资产参考在整个平台上保持一致.

我确信有更好的方法可以做到这一点,但它确实有效.

无论如何,这个应用程序只使用一个名为的纹理assets/plane.png.

写一些代码

您可以在libgdx存储库中找到大量示例.下面我将转储我用来测试本指南的代码.

主/ 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 );
  }
}
Run Code Online (Sandbox Code Playgroud)

主/ 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() {
  }
}
Run Code Online (Sandbox Code Playgroud)

安卓/ 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 );
  }
}
Run Code Online (Sandbox Code Playgroud)

桌面/ 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 );
  } 
}
Run Code Online (Sandbox Code Playgroud)

记得在处理android目标时进行审核AndroidManifest.xml.

编译桌面

这很容易.我们正在从ROOT目录运行编译命令.

# 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
Run Code Online (Sandbox Code Playgroud)

编译Android

比桌面更复杂一点.我在很大程度上扼杀了这个家伙的工作.该指南非常有用,值得一读,以解释我将在下面介绍的每个步骤.

我们正在从android目录运行命令.

首先我们制作R.java,我并不真正使用其中的任何资产,因为它击败了跨平台点,但似乎我无法在运行时没有出现错误的情况下删除它.

aapt package -v -f -m -M AndroidManifest.xml -I /opt/android-sdk/platforms/android-10/android.jar -S res -J src/ 
Run Code Online (Sandbox Code Playgroud)

现在我们编译我们的源文件.请注意,-classpath确保它与您的库所在的位置对齐.

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"`
Run Code Online (Sandbox Code Playgroud)

然后制作Dalvik字节码.包括代码中使用的所有库文件.

dx --dex --output bin/classes.dex bin/classes libs/gdx-backend-android.jar ../main/libs/gdx.jar
Run Code Online (Sandbox Code Playgroud)

这里我们制作我们的unsigned apk文件.

aapt package -v -f -M AndroidManifest.xml -S res -I /opt/android-sdk/platforms/android-10/android.jar -F bin/paperplanes.unsigned.apk bin/ 
Run Code Online (Sandbox Code Playgroud)

然后我们用钥匙签名.

jarsigner -verbose -keystore debugkey.keystore -storepass debug123 -keypass debug123 -signedjar bin/paperplanes.signed.apk bin/paperplanes.unsigned.apk debugkey
Run Code Online (Sandbox Code Playgroud)

如果您没有密钥,则可以生成密钥.这是如何制作一个(取自我经常提到的指南):

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
Run Code Online (Sandbox Code Playgroud)

最后我们运行zipalign并将其安装到设备上.

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
Run Code Online (Sandbox Code Playgroud)

来源

在命令行上构建Android程序

来自SO的答案让我失望

LibGDX github页面

PaperPlanes(这个项目)github页面

LibGDX API

制作应用程序时引用了LibGDX教程

制作应用程序时引用了另一个LibGDX教程