应用程序接口提供了丰富的方法来查找运行时环境的属性。
有时,对一些特殊案例来说,很有必要依赖于它所运行的平台而编写部分应用。Application.getApplicationType() 方法返回当前应用程序正在使用的平台。
switch(Gdx.app.getApplicationType()) { case ApplicationType.Android: // android specific code case ApplicationType.Desktop: // desktop specific code case ApplicationType.WebGl: /// HTML5 specific code }
Android中,也可查找当前应用运行的Android版本。
int androidVersion = Gdx.app.getVersion();
这会返回当前设备支持的SDK版本号,如:3 是 Android 1.5。
为了调试和分析,通常需要了解Java堆和本地堆的内存消耗。
int javaHeap = Gdx.app.getJavaHeap(); int nativeHeap = Gdx.app.getNativeHeap();
这两个方法都返回当前各自堆中已使用的字节数。
应用程序接口提供了一个简单的可控制粒度的日志工具。
一个信息可以是普通的info信息,可选异常的error信息和一个debug信息:
Gdx.app.log("MyTag", "my informative message"); Gdx.app.error("MyTag", "my error message", exception); Gdx.app.debug("MyTag", "my error message");
依赖于平台,这些信息被记录在控制台(桌面应用),LogCat(Android),或者是一个由GwtApplicationConfiguration提供或自动生成的GWT文本域(html5)。
日志可以指定为特定的日志级别:
Gdx.app.setLogLevel(logLevel);
其中 logLevel 可以是下面其中一个值:
所有的 ApplicationListener 的方法都在同一个线程里被调用。该线程是一个可创建OpenGL调用的渲染线程。对大多数游戏而言在方法ApplicationListener.render()中通过渲染线程同时实现逻辑更新和渲染就可以了。
任何直接涉及OpenGL的图形操作都需要在渲染线程里执行。在其他线程里操作会导致未知的行为。这是因为OpenGL上下文仅仅活跃于渲染线程内。在其他线程里创建当前上下文在很多Android设备上都有问题,因此不支持。
要想从其他线程向渲染线程传递数据,我们推荐使用 Application.postRunnable()。它会在ApplicationListener.render()调用前,使代码在下一帧里运行在渲染线程的Runnable中。
new Thread(new Runnable() { @Override public void run() { // do something important here, asynchronously to the rendering thread final Result result = createResult(); // post a Runnable to the rendering thread that processes the result Gdx.app.postRunnable(new Runnable() { @Override public void run() { // process the result, e.g. add it to an Array<Result> field of the ApplicationListener. results.add(result); } }); } }).start();
Javascript 一直是单线程的。因此,线程就不可用了。Web Workers 可能是未来的一种方法,然而,数据能够通过线程间信息进行传递。Java使用不同的线程原理和机制,不会直接移植线程代码到 Web Workers。
这里是相应的讨论区forum discussion,同时也包含iOS特定的东西。
有时需要访问平台特定API,例如:添加广告服务或者由框架提供的leaderboard,比如: Swarm。这可以通过用Facade实现这些API来完成,为每个目标提供平台特定的实现。
下面的例子纯属虚构,并假设想要使用一个非常简单的无继承的API,该API仅在Android上可用。对于其他平台,我们只记录调用信息或者提供一个模拟的返回值。
Android API 如下所示:
/** Let's assume this is the API provided by Swarm **/ public class LeaderboardServiceApi { public void submitScore(String user, int score) { ... } }
第一步是以接口的形式创建一个该抽象API。
该接口位于核心工程(see Project Setup):
public interface Leaderboard { public void submitScore(String user, int score); }
下一步,我们为每个平台创建具体实现,并把这些放置在各自工程内。
/** Android implementation, can access LeaderboardServiceApi directly **/ public class AndroidLeaderboard implements Leaderboard { private final LeaderboardServiceApi service; public AndroidLeaderboard() { // Assuming we can instantiate it like this service = new LeaderboardServiceApi(); } public void submitScore(String user, int score) { service.submitScore(user, score); } }
下面的代码放入桌面工程:
/** Desktop implementation, we simply log invocations **/ public class DesktopLeaderboard implements Leaderboard { public void submitScore(String user, int score) { Gdx.app.log("DesktopLeaderboard", "would have submitted score for user " + user + ": " + score"); } }
下面代码放进 HTML5工程:
/** Html5 implementation, same as DesktopLeaderboard **/ public class Html5Leaderboard implements Leaderboard { public void submitScore(String user, int score) { Gdx.app.log("DesktopLeaderboard", "would have submitted score for user " + user + ": " + score"); } }
接下来, ApplicationListener 实现一个构建器,这样就可以传入具体的 Leaderboard 实现:
public class MyGame implements ApplicationListener { private final Leaderboard leaderboard; public MyGame(Leaderboard leaderboard) { this.leaderboard = leaderboard; } // rest omitted for clarity }
然后在每个 启动类 中实例化 MyGame,传入相应的 Leaderboard 实现作为参数,如,桌面应用:
public static void main(String[] argv) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); new LwjglApplication(new MyGame(new DesktopLoaderboard()), config); }