背景
最近我想为Android构建一款游戏,并开始寻找一个好的图书馆来帮助解决这个问题。 LibGDX点击了所有正确的复选框。但是按照惯例(并且可以这么理解),所有文档都只提到使用Eclipse和ADT。以前,我使用Ant来构建我的Android项目,所以我假设我可以使用它但是学习Ant虽然可能很有用,但似乎有点考虑肯定没有那么多命令来构建项目?
问题
那么我需要做什么步骤来创建,编译和运行至少针对桌面和Android平台的LibGDX项目,而不使用Eclipse,Ant或其他IDE /构建工具?
我将回答我自己的问题,但我用来制作最终产品的方法可能不是最好的,所以欢迎批评。
答案 0 :(得分:11)
以下内容取自我制作的project on 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
这是大部分代码的用武之地。
cd main
mkdir -pv libs src/com/jeff/paperplanes
非常直接,与主要相同,但有bin
目录。
cd desktop
mkdir -pv bin/classes libs src/com/jeff/bucket
我们将使用android
工具生成的skelton项目构建android目录。或者,您可以按照sources部分中提供的guide自行创建目录结构。请注意--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
删除我们不需要的文件。我删除了progaurd文件,因为这个项目不需要它。
rm build.xml local.properties project.properties ant.properties proguard-project.txt
每晚下载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
安装时,apk需要包含areabi*
目录。因此,在bin/lib
目录中为这些文件夹创建一些链接。你也可以复制一下实际的文件夹,但是libs会进入libs目录这个文件!
cd android/bin/lib
ln -s ../../libs/armeabi
ln -s ../../libs/armeabi-v7a
与Android应用程序共享时,资产很奇怪。
桌面应用程序从应用程序的根目录开始查找assests,因此您可以像这样引用资产:
Gdx.files.internal( "assets/plane.png" )
但是,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 );
}
}
主要/ 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() {
}
}
<强>机器人/ 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 );
}
}
<强>桌面/ 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 );
}
}
请记住在处理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
比桌面更复杂。我在很大程度上扼杀了this guy所做的工作。该指南非常有用,值得一读,以解释我将在下面介绍的每个步骤。
我们正在运行android
目录中的命令。
首先我们制作R.java,我并不真正使用其中的任何资产,因为它胜过跨平台点,但似乎我无法在运行时发现错误而将其删除。
aapt package -v -f -m -M AndroidManifest.xml -I /opt/android-sdk/platforms/android-10/android.jar -S res -J src/
现在我们编译我们的源文件。请注意-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"`
然后制作Dalvik字节码。包括代码中使用的所有库文件。
dx --dex --output bin/classes.dex bin/classes libs/gdx-backend-android.jar ../main/libs/gdx.jar
这里我们制作未签名的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/
然后我们用钥匙签名。
jarsigner -verbose -keystore debugkey.keystore -storepass debug123 -keypass debug123 -signedjar bin/paperplanes.signed.apk bin/paperplanes.unsigned.apk debugkey
如果您没有钥匙,可以生成钥匙。以下是如何制作一个(取自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
最后我们运行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
Building Android programs on the command line
An answer from SO that set me off
PaperPlanes (this project) github page