以下内容来自我在 github 上创建的一个项目,其中包含所有代码和信息。
纸飞机
这是一个测试 libgdx 开发的简单应用程序,无需使用 Eclipse 或 Ant 来构建项目。主要关注点是将 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
设置桌面目录
非常简单,与 main 相同,但有一个bin
目录。
cd desktop
mkdir -pv bin/classes libs src/com/jeff/bucket
设置安卓目录
我们将使用该工具生成的 skelton 项目构建 android 目录android
。或者,您可以按照源代码部分中提供的指南自行创建目录结构。请注意--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 并将所需的库放在相关目录中。下面的片段是我如何更新我的库。
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 应用程序共享时,资产很奇怪。
桌面应用程序从应用程序的根目录开始查找资产,因此您可以像这样引用资产:
Gdx.files.internal( "assets/plane.png" )
assets
但是,android 应用程序会从目录中开始查找资产。因此,上面的代码会导致它在文件夹中查找文件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() {
}
}
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 );
}
}
桌面/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
编译安卓
比桌面复杂一点。我在很大程度上抄袭了这个人所做的工作。该指南非常有用,值得一读,以解释我将在下面执行的每个步骤。
我们正在从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
如果您没有密钥,您可以生成一个。以下是制作方法(摘自我经常提到的指南):
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
来源
在命令行上构建 Android 程序
SO的回答让我失望
LibGDX github页面
PaperPlanes(这个项目)github页面
LibGDX API
制作应用时参考的LibGDX教程
制作应用程序时参考的另一个 LibGDX 教程