這單元我們要開始實作,讓你的戰鬥機發射子彈。
參考其他射擊遊戲,很多都是直接觸控螢幕時就會開始發射子彈,當離開觸控時,子彈就會停止發射(或許有些此類型的射擊遊戲,連觸控都不用,就一直持續發射子彈,反正不發射的情況也不多見)
實現以上機制,首先我們先實作一個觸控的開關。
作法非常簡單,之前我們操作戰鬥機移動,是偵聽TouchEvent的TouchPhase.MOVED,這個開關,只要把TouchPhase.BEGAN,當成開,TouchPhase.ENDED則是關閉,就可以做到這個功能。
打開你遊戲專案的觸控控制TuochInputController.as
到onTOUCH的functiom,在TouchPhase.BEGAN加上triggerON("shoot"),TouchPhase.ENDED的時候triggerOFF("shoot")。
這是一個on與off的開關功能,還可以再傳一個字串參數(我們傳出"shoot")。
這樣做之後,只要判定TuochInputController控制器的開關on的時候,且參數是shoot,就代表開始發射子彈,反之則關閉。
接下打開遊戲場景MainStarlingState.as,我們先作一些準備,宣告等等用得到的變數
isShoot是發射子彈的開關,(其他的等等說明..)
下面是處理isShoot開關控制的部分。
78 79行,加上了對TuochInputController反應的控制函式,之前有說過,InputController反應控制的函式會傳入InputAction物件,你可以判定他的name屬性,檢查是不是我們傳入的參數shoot字串,然後把開關(isShoot)設定到應有的布林值。
以上你已經實作的觸控的開關。
接下來我們實作子彈的CitrusSprite物件
繼承CitrusSprite物件,第4行把素材圖片置中,第5行打開updata開關,第6行velocity屬性是速度,傳入一個陣列,[x速度,y速度],子彈一定是一直往上,所以給一個負值的y數據(這裡給-800)
updata中,每次更新都檢查是不是超過頂端(y<=-10),超過的話就移除。
這樣子子彈物件就完成了,之後把它增加到場景上,他自己就會往上移動,然後超過場景畫面就會把自己移除掉。
接下來,只要在isShoot==true的情況下,發射子彈就可以了。
首先先把子彈的素材拉出來。
再來在update得時候檢查isShoot是否為true
117~121行,這裡應該很單純,總之就是new一個子彈物件,把他加到畫面上,座標就是戰鬥機的位置(這樣子子彈才會從戰鬥機中發射出來)
104~113是每次update都會作的事,照理來說應該是我們只要判定isShoot的情況下就直接執行shoot(),把子彈發射出去就好,不過你會發現一個問題,就是子彈發射間格會很密集(與其說子彈不如說是雷射),原因是當isShoot=true時每個updata都會發射一發子彈,你可以去輸出看一下updata中傳入的timeDelta參數,這是每次update時與上一個update的間格時間,可能非常的小,而且還不一樣,所以只有光靠每個updata來作是不夠的。
現在我們需要的是,子彈格一段時間才會發射出來(即使isShoot一直是true的狀況)。
前面宣告變數時有一個SHOOT_D,我們把他設為0.1,這就是子彈射出的間格時間。
100行,宣告一個shootTimeTmp暫存一下累積的時間,105行,每次update時就累加這個值,108行,每當shootTimeTmp超過我們設定的SHOOT_D時,才發射子彈,然後把shootTimeTmp歸0,重新累加,這樣子的流程就可以做到子彈連續發射,且時間間格也固定。
好了之後你可以輸出到你的手機上看看是否可以正常運作。
以上看起來似乎都一切正常,不過手機上要注意的事情不只有畫面而已,其實更重要的是資源與效能上的調校。目前的作法,是一直不斷的new子彈物件,然後超過螢幕就移除回收。理論看起來是沒有問題,不過所謂的回收也不過是系統每格一段時間,把沒用的物件釋放掉,但是我們卻不知道實際上何時會釋放。 像是發射子彈這種動作,你可以能在1分鐘內,new出了上百(或者更多)的物件,我們不能保證他何時會回收,況且一直作new這個動作,實際上對效能來說,也是相當不利,難免不對系統效能照成影響,可以的話,我們不希望一直做這樣的動作。 關於這個問題,下一篇我們將利用一種元件釋放池(release pool)的概念來解決這個問題。
Flash遊戲引擎 CitrusEngine (十二) 開始你的第一個行動APP遊戲吧 - 利用Release Pool管理你的物件
沒有留言:
張貼留言