Andriod游戲開發(fā) 第九章 游戲程序的生命周期2_第1頁
Andriod游戲開發(fā) 第九章 游戲程序的生命周期2_第2頁
Andriod游戲開發(fā) 第九章 游戲程序的生命周期2_第3頁
Andriod游戲開發(fā) 第九章 游戲程序的生命周期2_第4頁
Andriod游戲開發(fā) 第九章 游戲程序的生命周期2_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

從零開始Android游戲編程(第二版)第九章游戲程序的生命周期\o"收藏到我的網(wǎng)摘中,并分享給我的朋友"收藏第九章游戲程序的生命周期在講解游戲程序的生命周期之前,讓我們先看看普通Android應用的生命周期。關(guān)于生命周期,SDK附帶的文檔上有詳細的解釋,讓我們打開文檔,找到andorid.app->Activity,我們會看到這樣一張圖片圖片將整個程序的生命周期描述的非常清楚,為了加深理解,我們創(chuàng)建一個程序?qū)嶋H看一下這個過程。創(chuàng)建項目LifeCycle,sdk就選擇1.6吧。在Activity中重載如下幾個函數(shù),并增加Log語句:@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);LogF();}@OverrideprotectedvoidonDestroy(){//TODOAuto-generatedmethodstubsuper.onDestroy();LogF();}@OverrideprotectedvoidonPause(){//TODOAuto-generatedmethodstubsuper.onPause();LogF();}@OverrideprotectedvoidonRestart(){//TODOAuto-generatedmethodstubsuper.onRestart();LogF();}@OverrideprotectedvoidonResume(){//TODOAuto-generatedmethodstubsuper.onResume();LogF();}@OverrideprotectedvoidonStart(){//TODOAuto-generatedmethodstubsuper.onStart();LogF();}@OverrideprotectedvoidonStop(){//TODOAuto-generatedmethodstubsuper.onStop();LogF();}LogF()定義如下:publicstaticvoidLogF(){Log.v(Thread.currentThread().getStackTrace()[3].getClassName(),Thread.currentThread().getStackTrace()[3].getMethodName());}除了onCreate之外,都需要手工添加,重載函數(shù)的方法前面有哦,一年過去了,大家沒忘吧:)讓我們在模擬器中運行這個程序。同時在LogCat中查看輸出。前面好像沒有講到LogCat,但是很多代碼用到了Log,大家都已經(jīng)找到了吧。程序啟動后,我們看到了3條自定義的Log信息:讓我們按下返回鍵結(jié)束程序,這就是一個程序從創(chuàng)建到銷毀的標準流程。但是作為手機應用,我們前面提到的被搶占屏幕的情況就必須要被考慮。讓我們來測試一下:重新運行LifeCycle,在DDMS中模擬一個電話呼入日志中出現(xiàn)了這次沒有調(diào)用onDestory。然后讓我們把電話掛掉同樣,沒有調(diào)用onCreate而調(diào)用了onRestart。另外還有一種情況,就是當程序被放置到后臺過久,系統(tǒng)在一定條件下會自動將程序銷毀,讓我們看一下這種情況下程序的生命周期會有什么變化。運行LifeCycle,轉(zhuǎn)到DDMS,模擬一個來電,然后在Devices找到LifeCycle并強行停止他我們會發(fā)現(xiàn)日志中并沒有任何輸出。這時,讓我們掛掉電話,日志中出現(xiàn)了如下三行可以看到,程序被重新創(chuàng)建了,調(diào)用了onCreate而不是onRestart,這與我們前面說的流程相悖,因為在這種情況下,我們應該繼續(xù)程序的執(zhí)行而不是重新初始化。那么如何解決這個問題呢?方法如下,讓我們重載下面這個函數(shù):@OverrideprotectedvoidonSaveInstanceState(BundleoutState){//TODOAuto-generatedmethodstubsuper.onSaveInstanceState(outState);Log.v(this.toString(),Thread.currentThread().getStackTrace()[2].getMethodName());}重新?lián)苋腚娫?,日志中出現(xiàn)了如下內(nèi)容可以看到,在onPause之前執(zhí)行了onSaveInstanceState。那么執(zhí)行了它有什么作用呢?是不是就已經(jīng)把程序狀態(tài)保存了呢?還沒有,保存的過程需要我們自己來編碼。我們拿這個函數(shù)與其他的onXXX對比會發(fā)現(xiàn),它與onCreate一樣,都有一個Bundle類型的參數(shù),而缺省的名字似乎已經(jīng)透露了玄機,onCreate的參數(shù)名叫savedInstanceState,意為被保存的狀態(tài),正與onSavedInstanceState對應,那么名為outState意為輸出狀態(tài)的參數(shù),功能就不言自明了。把需要保存的值放到outState中,在onCreate中檢查savedInstanceState是否為null,如果有值就取出來恢復現(xiàn)場。具體的用法,學習了游戲程序的生命周期之后會有實例講解。前面講的是一個普通應用程序的生命周期,下面讓我們進一步了解一個游戲程序的生命周期。我們的游戲同樣基于SurfaceView。根據(jù)前面講過的內(nèi)容,我們知道,現(xiàn)在程序中增加了游戲循環(huán),它是一個單獨的線程,因此在程序的生命周期中就增加了對游戲線程的操作。在LifeCycle中增加GameView,繼承自SurfaceView,實現(xiàn)SurfaceHonder.Callback和Runnable接口(前面已經(jīng)講過哦)。重載函數(shù),并在函數(shù)中添加Log。修改onCreate使其顯示GameView。讓我們運行程序看看Log的輸出:啟動程序來電呼入通話結(jié)束應用結(jié)束再追加兩種前面沒有講到的情況,一是屏幕翻轉(zhuǎn)(在模擬器中的快捷鍵是Ctrl+F11)可以看到,如果程序沒有設(shè)置固定的橫屏或豎屏狀態(tài),每次翻轉(zhuǎn)屏幕,就會將程序關(guān)閉并重新啟動。另一種情況是休眠。當我們沒有強制應用不休眠時,或短暫按下電源鍵時,應用會進入暫停狀態(tài),屏幕上顯示鎖屏畫面。讓我們解鎖屏幕,應用被喚醒,繼續(xù)執(zhí)行,讓我們看一下此時的Log:前面我們也講過,我們在一個獨立的線程中進行游戲循環(huán),依照一般應用的生命周期,在適當?shù)臅r候開始和結(jié)束游戲循環(huán),保存游戲狀態(tài),就能夠完美的控制游戲程序的生命周期了。首先讓我們用文字總結(jié)一下這個過程:在onCreata中,初始化游戲狀態(tài)或恢復游戲狀態(tài)。注意,這里不是初始化圖片,聲音等數(shù)據(jù)(Data),只是游戲內(nèi)狀態(tài),比如現(xiàn)在是開始菜單還是在游戲當中,玩家的位置,敵人的位置等等數(shù)值(Value);在onRestart中恢復游戲狀態(tài);在onResume中開始游戲循環(huán)(本應在onStart中,但是我們看到,各種情況下,onResume都會在onStart之后調(diào)用,所以簡單的用onResume代替了onStart);在onSaveInstanceState中保存游戲狀態(tài);在onPause中結(jié)束游戲循環(huán);在onDestory中銷毀游戲數(shù)據(jù)。另外補充幾句,游戲的保存和讀取實際上是不屬于應用程序生命周期的,而是一種游戲內(nèi)操作。但是,你也可以根據(jù)程序的生命周期來決定是否應該保存和讀取游戲,比如實現(xiàn)自動保存,以防止程序意外終止造成的損失。最后,就讓我們用一個程序來演示本章所講的內(nèi)容。我們依然使用計時器程序來演示,因為他很直觀。程序的關(guān)鍵點在于當程序被隱藏時,停止計時,被重新顯示時繼續(xù)計時。首先在游戲進程開始后進行計時,我們首先要取得開始的時間:publicvoidrun(){start=System.currentTimeMillis();while(run){now=System.currentTimeMillis();……那么計時器顯示的數(shù)值就是當前時間now減去開始時間start,為了便于觀察,我們用秒作為單位,就是(now–start)/1000。在程序被暫停后,我們需要停止游戲循環(huán),可以終止線程也可以停止對數(shù)值的計算,本例中我們選擇終止線程。我們?yōu)镚ameView增加函數(shù)pausepublicvoidpause(){run=false;}如果現(xiàn)在運行程序,我們會發(fā)現(xiàn),程序被暫停再恢復就會重新計時,那么如何在程序恢復后繼續(xù)計時呢?我們要在暫停時將當前的時間保存起來,恢復后就可以用now-start加上這個時間,就實現(xiàn)連續(xù)計時了。我們設(shè)定變量last保存上次時間,那么計時器當前的值就是millis=last+now-start;而pause函數(shù)修改成publicvoidpause(){run=false;last=millis;}這樣就解決了重新計時的問題。但是別忘了,前面我們還特別提到一種情況,就是程序會被系統(tǒng)銷毀,并重新執(zhí)行,那么這種方案就不適用了,因為程序重新執(zhí)行時,last會被重新初始化,保存的值也就隨之丟失了。當然,聰明的讀者肯定記得前面我們說過的onSaveInstanceState,沒錯,下面就是它發(fā)揮作用的時候了。首先我們在GameView中創(chuàng)建函數(shù)savepublicvoidsave(BundleoutState){outState.putLong("last",millis);}前面沒有講解Bundle,下面就讓我們看看他的用法。如果你了解Map,你會發(fā)現(xiàn)兩者很相似,他們都可以用來存儲key-value值對,讀取方法也一樣,只是Bundle的函數(shù)設(shè)定了變量類型而已。有了保存就有讀取,讓我們增加load函數(shù)publicvoidload(BundlesavedInstanceState){if(savedInstanceState!=null){last=savedInstanceState.getLong("last");}}最后我們再增加一個resume函數(shù),來啟動線程,前面說過resume和start起著同樣的作用publicvoidresume(){run=true;newThread(this).start();}到此為止,我們已經(jīng)有了控制游戲進程的所有函數(shù),下一步就是在Activity中相應的回調(diào)函數(shù)中調(diào)用這些函數(shù)了,具體怎么調(diào)用,我想讀者心中已經(jīng)有數(shù)了吧。當然,你可以在本章的例程中找到完整的代碼。這個例子雖然簡單,但即使是很復雜的游戲(使用SurfaceView)也可以通過這個方法來控制。但是細心的讀者可能會發(fā)現(xiàn),例子程序有一些誤差,因為在surface還沒有被創(chuàng)建時游戲循環(huán)就已經(jīng)開始了,所以可能會直接看到屏幕顯示3、4等,這當然不是致命的問題,因為大多數(shù)游戲不是

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論