一步一步教你用Swift開發俄羅斯方塊:No.4 滴答作響的時鐘機制,swiftno.4
為什麼標題要叫做“滴答作響的時鐘機制”呢?
想必我們大家都玩過俄羅斯方塊,那些不同形狀的東西,就是哪些不同形狀,你懂的,會隨著遊戲層級的提高而下降的越來越快。是的 ,我們也要模仿那樣,做出我們自己的時鐘機制。
我們可以看到SKScene裡面有一個函數update(currentTime: CFTimeInterval)。 這個函數被沒一幀所調用。幀,frame, 是什嗎? 你可以理解一幀就是一副靜態圖片,如果很多圖片在很短的時間內連續播放,就成了動畫。當你的眼睛開始去預知每一幀映像的時候,你的遊戲會看起來有些慢,我們來看下面的這個GIF圖片,你是不是會覺得60fps的時候那個球看起來跑的沒有下面的球塊一樣?
我特意去查了一下什麼叫 motion blur , 其實就是攝影裡面的慢速快門一樣。
ok介紹完幀,我們來修改我們GameScene中的update函數,照著下面這個圖修改吧:
好的,讓我們繼續來分段講解下這次的更新吧。
#1
首先我們定義了一個常量,TickLengthlevelOne, 這個常量將會用來顯示我們最慢的遊戲速度,因為每一幅圖片之間的間隔越長,它就看起來越慢,對吧?
我們先把它設定成600毫秒,也就是說每隔0.6秒,我們的形狀將會往下掉落一行。
#2
我們定義了一些新的變數。
tickLengthMillis和lastTick很簡單,我們之前已經遇到過這樣的定義方式。第一個被賦予之前我們已經定義過的常量TickLenghtLevelOne;第二個用來表示我們最後一次記錄的時間,一個NSDate類型的執行個體。
但是,但是,你知道tick:(()->())? 是個什麼嗎?它看起來確實非常詭異的。
tick其實是一個在swift被叫做閉包(closure)的東西,如果你熟悉object-c ,那麼閉包就是那裡面的塊(block)。
之前我們已經接觸過函數的定義方式,知道了 -> 這個符號的意思,那在tick裡面,(()->())? 表示這個閉包不需要參數,也不返回任何東西。因為它是optional的,所以它當然有可能是nil。
剛開始學的時候,我對這個()->()百思不得其解,它不需要任何參數,它又返回了noting,那它是幹嘛的?後來沒憋住上Stackoverflow上問了有位大神的回複讓我總算明白了它的含義。
是的,在這裡,到目前為止,我們這個tick,指向函數的你叫它變數也好,叫它指標也罷,我們叫它closure;目前為止,這個closure沒有什麼意義,它就是一個佔位的,告訴你這裡是有個東西的,當然,到項目的中期,我們的tick 閉包就會派上用處了。
所以大家不要急,你可以認為這裡的closure就是個預留位置,好比我先把樓給佔了,等我想好說什麼了我在說,而且這次覺得說的不好,我還可以換,就這麼nb。
關於closure的更多官文文檔,請點擊這裡
我也推薦另外一個中文翻譯的
關於閉包的更清晰而且傳神的文章
你可以在那裡看到更多神奇的特性
#3
讓我們接著往下看,我們將會引入一個新的變數。
如果lastTick是nil,那麼我們當前處於一個暫停狀態,所以我們直接return就好了,不需要做任何動作;但是如果不是,說明目前遊戲是在進行中的,我們得做點什麼東西。
timePassed這個變數從它的名字上就能看出來是表示過去了多久的一個變數,過去多久,和啥時候作為參照呢?把lastTick和now作為比較,因為lastTick記錄的是最後一次記錄的時間點,那它相對現在肯定是倒退的,所以,timeIntervalSinceNow這個函數可以返回和當前的時間比相差多少。因為是過去的時間點,所有這個值肯定是負數,而且單位是毫秒,所以我們需要* -1000 把它變成一個正的而且單位是秒的數,因為我們的tickLengthMillis可是0.6秒。
也就是說 如果現在的時間和最後一次記錄的時間間隔超過了0.6秒,我們就執行接下來的動作:
記錄下當前的時間,然後tick一下;
在現在這個階段,因為tick是個真正空的東西,所以不會發生什麼,但是你要知道,它是可以發生點什麼的,只要我們賦予tick某個函數就行了。
因為我們用到了lastTick.timeIntervalSinceNow, 所以感興趣的東西學深入學習一下swift的dot文法