1. 程式人生 > >Libgdx Developer's Guide(Libgdx開發者手冊)-7(查詢,日誌,執行緒,特定平臺程式碼的介面)

Libgdx Developer's Guide(Libgdx開發者手冊)-7(查詢,日誌,執行緒,特定平臺程式碼的介面)

查詢

應用程式介面提供了豐富的方法來查詢執行時環境的屬性。

獲取應用型別

有時,對一些特殊案例來說,很有必要依賴於它所執行的平臺而編寫部分應用。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 可以是下面其中一個值:

  • Application.LOG_NONE: 忽略所有記錄。
  • Application.LOG_DEBUG:記錄所有資訊。
  • Application.LOG_ERROR:只記錄錯誤資訊。
  • Application.LOG_INFO: 記錄錯誤與正常資訊。

執行緒

所有的 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();

HTML5

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工程:
/** 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);
}