针对不同的平台,启动类需要被重写,该启动类实例化不同平台特定的 Application&ApplicationListener 实现,启动类是平台相关的,让我们来深入了解下如何为 不同的平台创建和配置 启动类.
当然,在学习这篇文章时,你也可以事先了解下 Project Setup, Running & Debugging
桌面应用 Desktop (LWJGL)
打开my-gdx-game项目的Main.java文件:
package com.me.mygdxgame;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "my-gdx-game";
cfg.useGL30 = false;
cfg.width = 480;
cfg.height = 320;
new LwjglApplication(new MyGdxGame(), cfg);
}
}
首先,实例化一个LwjglApplicationConfiguration。 该类可以指定各种配置设置,如初始屏幕分辨率,是否使用OpenGL ES 2.0或3.0(处于实验中)等。 有关更多信息,请参阅此类的Javadocs。
桌面应用 Desktop (LWJGL3)
To come...
Android
Android应用程序不使用main()方法作为入口点,而是需要一个Activity。 打开my-gdx-game-android项目中的MainActivity.java类:
package com.me.mygdxgame;
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
public class MainActivity extends AndroidApplication {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
initialize(new MyGdxGame(), cfg);
}
}
Android 主要的入口方法是Activity的onCreate()方法。 请注意,MainActivity源自AndroidApplication,它本身来自“Activity”。 和桌面启动器类一样,创建一个配置实例(AndroidApplicationConfiguration)。 配置完成后,将调用AndroidApplication.initialize()方法,并将(AndroidApplicationConfiguration,MyGdxGame)作为参数进行传递。 有关可用的配置设置的更多信息,请参阅AndroidApplicationConfiguration 的Javadocs。
Android应用程序可以有多个Activity。 Libgdx游戏通常只能由一个Activity组成。 游戏的不同screens (屏幕)由libgdx的相关方法进行实现,而不是单独的Activity。 这样做的原因是,创建一个新的Activity也意味着创建一个新的OpenGL上下文,这非常耗时(意味着必须重新加载所有图形资源).
基于片段(Fragment )的libgdx
Android SDK引入了一个API来为屏幕的特定部分创建控制器,可以在多个屏幕上轻松重新使用。 该API称为Fragments API。 现在Libgdx也可以创建Fragment来用作一个大的screen的一部分。 要创建一个Libgdx片段,需要继承子类AndroidFragmentApplication,并重写onCreateView()方法:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return initializeForView(new MyGdxGame());
}
该代码取决于-android项目的其他一些更改:
- 添加V4支持
- 修改AndroidLauncher 继承 FragmentActivity 而非(AndroidApplication)
- 在AndroidLauncher 页面实现AndroidFragmentApplication.Callbacks 回调
- 创建一个扩展AndroidFragmentApplication的类,这是Libgdx的Fragment实现。
- 在Fragment的onCreateView方法中添加initializeForView()代码。
- 最后,用Libgdx Fragment替换AndroidLauncher activity 中的内容。
例如:
// 2. Change AndroidLauncher activity to extend FragmentActivity, not AndroidApplication
// 3. Implement AndroidFragmentApplication.Callbacks on the AndroidLauncher activity
public class AndroidLauncher extends FragmentActivity implements AndroidFragmentApplication.Callbacks
{
@Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// 6. Finally, replace the AndroidLauncher activity content with the Libgdx Fragment.
GameFragment fragment = new GameFragment();
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(android.R.id.content, fragment);
trans.commit();
}
// 4. Create a Class that extends AndroidFragmentApplication which is the Fragment implementation for Libgdx.
public static class GameFragment extends AndroidFragmentApplication
{
// 5. Add the initializeForView() code in the Fragment's onCreateView method.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ return initializeForView(new MyGdxGame()); }
}
@Override
public void exit() {}
}
The AndroidManifest.xml File
除了AndroidApplicationConfiguration之外,Android应用程序也通过AndroidManifest.xml文件进行配置,该文件位于Android项目的根目录中。 这可能看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.me.mygdxgame"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
目标Sdk版本
将其设置为要定位的Android版本。
屏幕方向和配置更改
除了targetSdkVersion之外,应始终设置activity元素的screenOrientation和configChanges属性。
screenOrientation 属性指定应用程序的固定方向。 如果应用程序可以同时使用横向和纵向模式,也可以省略此选项。
configChanges属性至关重要,应始终包含上面显示的值(screenOrientation )。 省略此属性意味着每次物理键盘滑出/插入时或如果设备的方向改变时,应用程序将重新启动。 如果省略screenOrientation属性,则libgdx应用程序将接收到ApplicationListener.resize()的调用,以指示方向更改。 API客户端可以相应地重新布置应用程序。
权限
如果应用程序需要能够写入到外部存储设备(例如SD卡),需要互联网访问,使用振动器或要录制音频,则需要将以下权限添加到AndroidManifest.xml文件中:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
用户通常怀疑有许多权限的应用程序,所以不要滥用申请权限。
要唤醒锁定工作,AndroidApplicationConfiguration.useWakeLock需要设置为true。
如果游戏不需要加速度计或指南针访问,建议您将AndroidApplicationConfiguration的useAccelerometer和useCompass字段设置为false来禁用这些。
如果您的游戏需要陀螺仪传感器,则必须在AndroidApplicationConfiguration中将useGyroscope设置为true(默认情况下禁用它,以节省能量)。
有关如何设置其他属性(如应用程序的图标)的详细信息,请参阅Android Developer's Guide 。
动态壁纸
Libgdx提供了一种简单的使用方法来创建Android壁纸。 活动壁纸的起始类称为AndroidLiveWallpaperService,以下是一个例子:
package com.mypackage;
// imports snipped for brevity
public class LiveWallpaper extends AndroidLiveWallpaperService {
@Override
public ApplicationListener createListener () {
return new MyApplicationListener();
}
@Override
public AndroidApplicationConfiguration createConfig () {
return new AndroidApplicationConfiguration();
}
@Override
public void offsetChange (ApplicationListener listener, float xOffset, float yOffset, float xOffsetStep, float yOffsetStep,
int xPixelOffset, int yPixelOffset) {
Gdx.app.log("LiveWallpaper", "offset changed: " + xOffset + ", " + yOffset);
}
}
当动态壁纸在选择器或者主界面上显示时,将调用createListener()和createConfig()方法。
当用户通过主屏幕上的屏幕滑动时,offsetChange()方法会缩放,并告诉您屏幕偏离中心屏幕的程度。 这个方法将在渲染线程上被调用,所以你不需要同步任何东西。
除了起始类外,您还必须创建一个描述您的壁纸的XML文件,文明给这个xml文件命名为livewallpaper.xml。 在您的Android项目的res /文件夹中创建一个名为xml /的文件夹,并将文件放在(res / xml / livewallpaper.xml)中。 以下是该文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="@drawable/ic_launcher"
android:description="@string/description"
android:settingsActivity="com.mypackage.LivewallpaperSettings"/>
该xml定义了在选择器上的缩略图,当用户在应用的选择器中点击“设置”将显示 说明及活动。这应该只是一个标准的Activity,它具有几个小部件来更改背景颜色和类似的设置。您可以将这些设置存储在SharedPreferences中,并通过Gdx.app.getPreferences()稍后加载到LWPs 的ApplicationListener中。
最后,您需要在AndroidManifest.xml文件中添加一些内容。 以下是一个包含简单设置界面的LWP的应用例子:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14"/>
<uses-feature android:name="android.software.live_wallpaper" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LivewallpaperSettings"
android:label="Livewallpaper Settings"/>
<service android:name=".LiveWallpaper"
android:label="@string/app_name"
android:icon="@drawable/icon"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/livewallpaper" />
</service>
</application>
</manifest>
解析:
- 它使用动态壁纸功能,请参阅<uses-feature>。
- 允许绑定壁纸,请参阅android:permission
- 设置活动
- Livewallpaper服务指向livewallpaper.xml文件,请参阅 meta-data
请注意,只有Android 2.1(SDK级别7)才支持动态壁纸。
LWP应用对触摸输入有一些限制。 一般只有轻触/点击才会被上报。 如果您想要全触摸,您可以设置AndroidApplicationConfiguration#getTouchEventsForLiveWallpaper标志为true,以接收完整的多点触控事件。
Daydreams
从Android 4.2开始,用户可以设置Daydreams,如果设备空闲时Daydreams将会显示。 这些Daydreams类似于屏幕保护程序,可以显示像相册等的内容。Libgdx让我们轻松写出这样的Daydreams。
Daydreams的基类是AndroidDaydream,以下是一个Daydreams的简单实例(AndroidDaydream):
package com.badlogic.gdx.tests.android;
import android.annotation.TargetApi;
import android.util.Log;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.badlogic.gdx.backends.android.AndroidDaydream;
import com.badlogic.gdx.tests.MeshShaderTest;
@TargetApi(17)
public class Daydream extends AndroidDaydream {
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
setInteractive(false);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
ApplicationListener app = new MeshShaderTest();
initialize(app, cfg);
}
}
简单地从AndroidDaydream派生,重写onAttachedToWindow,设置您的配置和ApplicationListener并初始化您的Daydreams。
除了Daydreams之外,您还可以提供设置Activity,让用户配置您的Daydreams.这可以是一个正常的Activity,或者一个libgdx的AndroidApplication。 以一个空Activity为例:
package com.badlogic.gdx.tests.android;
import android.app.Activity;
public class DaydreamSettings extends Activity {
}
必须将此设置活动指定为Daydream服务的metadata 。 在Android项目的res / xml文件夹中创建一个xml文件,并指定如下活动:
<dream xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.badlogic.gdx.tests.android/.DaydreamSettings" />
最后,像往常一样在AndroidManifest.xml中添加一些设置activity的部分,以及daydream的服务描述,如下所示:
<service android:name=".Daydream"
android:label="@string/app_name"
android:icon="@drawable/icon"
android:exported="true">
<intent-filter>
<action android:name="android.service.dreams.DreamService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.service.dream"
android:resource="@xml/daydream" />
</service>
由于暂时不准备涉及HTML5,如需要,后期会进行补充.