AndEngine引擎基礎構成如所示: 一、如何使用AndEngine: 1.1 AndEngine的基本運行原理: 解讀AndEngine源碼後我們可以發現,AndEngine除了採取低耦合、高內聚的架構策略細分引擎模組,使用OpenGLES進行遊戲渲染之外;該引擎還以雙線程方式分別驅動繪圖與事務更新,事實上,它將遊戲畫面和遊戲業務分為兩組邏輯,並行跑在同級的互斥線程當中。 具體地說,其繪圖線程位於AndEngine提供的GLSurfaceView內部類GLThread(在AndEngine的org.anddev.andengine.opengl.view包下,非Android預設的GLSurfaceView),並通過GLSurfaceView子類,即AndEngine提供的RenderSurfaceView類調用重載的onDrawFrame函數加以渲染控制;而業務線程在Engine類的內部類UpdateThread中,AndEngine將始終以while(true)這樣的死迴圈方式快速執行其中的onTickUpdate函數,所有AndEngine提供的遊戲業務最終都會由此函數調用及執行,比如AndEngine常用的registerUpdateHandler方法就是向它提交資料。 當AndEngine進行遊戲繪圖時,遊戲業務線程會通過wait方式鎖定,而當遊戲業務處理時,也會以同樣的手段鎖定繪圖線程,二者間具體互動關係由Engine類中的State子類控制,以此保證遊戲畫面與遊戲業務同步。 另外,或許是考慮到持續雙線程運行電量消耗較大的緣故,AndEngine預設情況下要求使用者啟動PowerManager進行電源管理,故此需要<uses-permission android:name="android.permission.WAKE_LOCK"/>許可權支援,否則初始化時Log會提示缺少相關配置,並建議你在AndroidManifest.xml中添加許可權。PS:無此許可權不影響運行,只會在Log有警告資訊,並且耗電較快。 1.2 AndEngine的基本運行流程: 由於AndEngine是專供Android使用的2D遊戲引擎,所以作為啟動類的Activity肯定必不可少,而AndEngine也理所應當的提供給我們這樣一個Activity,那就是BaseGameActivity。 一個標準的AndEngine應用,至少應該對BaseGameActivity做如下繼承:[java] www.2cto.compublic class Main extends BaseGameActivity { public void onLoadComplete() { } public Engine onLoadEngine() { return null; } public void onLoadResources() { } public Scene onLoadScene() { return null; } } 其中四個必須被重載函數的啟動順序如下: onLoadEngine->onLoadResources->onLoadScene->onLoadComplete 具體的講,AndEngine會首先載入Engine類執行個體通知系統遊戲引擎的基本運行方式,而後載入遊戲資源,其次載入遊戲情境執行個體,最後通過onLoadComplete通知使用者載入完畢並於此進行善後工作。 此外,由於BaseGameActivity類重載了父類Activity的onResume與onPause函數以保證其自身的正常運行,所以不建議在繼承BaseGameActivity時再次重載上述函數(重載的話不要忘記super調用),推薦直接重載AndEngine提供的onGamePaused和onGameResumed實現同等功能(最近把LGame也加上了這樣的兩個函數,並且禁止了LGameAndroid2DActivity子類重載onResume與onPause,務求減少使用者錯誤重載導致的程式異常)。 1.3 AndEngine的基本運行方式: 上文介紹了AndEngine的基本運行機制與運行流程,然而僅僅這樣AndEngine還是無法實際運行,因為Engine與Scene都沒有獲得具體實現。假如我們想要在螢幕上顯示出當前應用FPS數,至少需要做如下改動,才能滿足一個最為基本的AndEngine應用:[java] public class Main extends BaseGameActivity { private static final int CAMERA_WIDTH = 320; private static final int CAMERA_HEIGHT = 480; private Camera andCamera; private Texture myFontTexture; private Font myFont; public void onLoadComplete() { } public Engine onLoadEngine() { // 構建攝像機 this.andCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT); // 構建Engine,全螢幕顯示,手機方向為豎屏,按比例展開 return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.andCamera)); } public void onLoadResources() { // 構建一個紋理用以顯示文字 this.myFontTexture = new Texture(256, 256, TextureOptions.DEFAULT); // 構建字型 this.myFont = new Font(this.myFontTexture, Typeface.create( Typeface.DEFAULT, Typeface.BOLD), 32, true, Color.WHITE); // 注入相關紋理及字型 this.mEngine.getTextureManager().loadTexture(this.myFontTexture); this.mEngine.getFontManager().loadFont(this.myFont); } public Scene onLoadScene() { // 構建情境,允許的最大Layer數量為1 final Scene scene = new Scene(1); // 使用可以變更內容的ChangeableText顯示FPS(它的父類Text不允許改變顯示內容),位置在15,5, // 字型為myFont中所規定的,最多允許顯示5個字元(設定能顯示幾個字元,實際就能顯示幾個, // AndEngine不能自動擴充,不填以初始化時輸入的字元數計算……) final ChangeableText text = new ChangeableText(5, 5, this.myFont, "0.0", 5); // 註冊FPS監聽 this.mEngine.registerUpdateHandler(new FPSLogger() { protected void onHandleAverageDurationElapsed(final float pFPS) { super.onHandleAverageDurationElapsed(pFPS); // 傳遞內容到ChangeableText text.setText("" + pFPS); } }); // 將ChangeableText注入情境 scene.attachChild(text); // 構建情境,可容納圖層數為1 return scene; } }