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

付費(fèi)下載

下載本文檔

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

文檔簡(jiǎn)介

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論