iOS平台上aa(見縫插針)遊戲的簡易實現

來源:互聯網
上載者:User

標籤:開發   不同   解決方案   this   旋轉   而且   insert   是你   append   

前言

還記得那是2015年的6月的一場雨後(一場雨,把我困在這裡……),老姐拿來了她在QQ空間裡看到的一個有趣的遊戲:見縫插針。(當時還沒入移動開發這行,還是一個剛讀大學的愣頭青,不知道這是iOS平台上率先推出一款風靡全球的經典休閒遊戲:aa)這個網頁版的使用者體驗就沒有移動端的感覺好了,不過這都是後來才知道的。誒,這遊戲乍一看下不會覺得太難,然後你可能會很快地通過了前面幾個很簡單的關卡(我最初接觸到的只有15關),然後你在8、9關左右可能就會第一次失敗,然後很蛋疼的發現遊戲又從第1關開始了。一兩次還好,要是你好不容易克服“艱難險阻”來到了12、13關,再給你整這麼一出,內心的陰影面積可想而知,摔手機的心情都有了!

在“入坑”之後,面對這些東西就不會只是純粹地欣賞和玩樂了,而是總會下意識地思考這個效果可以兌現為怎樣的一段代碼。然後藉由這個思考結果不斷在開發工具裡搗鼓摸索著,終於有一日靈光一閃,實驗樣品出來了。隨即又因按捺不住內心的衝動,想要通過某種渠道寫點什麼東西來分享這麼一個實踐過程,於是就有了這麼一篇文章:iOS平台上aa(見縫插針)遊戲的簡易實現。

知己知彼,百戰不殆

玩過aa的朋友都知道,它的遊戲邏輯是這樣的:每一關你都有不同數量的“針”,中心的圓盤上初始狀態可能就會有“針”已經插入就緒,不過這是為增加遊戲難度而設計的。你的任務就是將你所在關卡中所持有的所有“針”插入到中心轉動的圓盤上去(插入點是相對固定的),前提是不能與其他“針”相互接觸,否則遊戲宣告失敗。為了不讓你很快通關,後面的關卡理所當然難度會越來越大,比如圓盤轉速增加、初始就緒“針”數和持有針數增加、順逆時針變速轉動(最坑的就是這一點,我在這上面載了不少跟頭!),這裡之所以叫做簡易實現主要是因為Demo只是簡單實現了遊戲邏輯,沒有設定多重關卡,取而代之的是所謂的無盡模式。

因為開始實踐這個遊戲時,我已經快要期末考試了,所以需要著手準備考試和實習的事情,沒有太多的精力去設計遊戲的美化和後繼的關卡。當然,如果後面有機會的話,應該會有Demo2.0版本。

關於這個遊戲的實現,我最開始的想法就是當你點擊螢幕時,擴充中心圓盤(CAShapeLayer執行個體)的path屬性,以達到最終“針”插在圓盤上的效果。對於“針”的動態移動過程, 就可以建立一個過渡的“針”視圖來等效代替。那麼核心的問題就來了:我在擴充圖層的路徑時,怎麼確定繪製的起始點和終點呢?因為在中心圓盤的旋轉過程中,其上的個點也會隨之一起做仿射變換。如果你在圖層旋轉時還是以圓盤靜止時寫入程式碼取到的起點和終點來確認繪製“針”的話,那麼新繪製的“針”就會和之前“插上”的“針”重合在一起,導致的結果就是:無論你怎麼“插針”,圓盤上看到的就只有一根“針”,雖然實際上它是很多“針”重疊在一起而表現出來的結果。

那麼首要問題就是如何得到當前“針”的繪製起點和終點?

實踐是檢驗真理的唯一標準

值得慶幸的是中心轉軸是圓形的(故稱之為圓盤),而且也只能是在圓形的情況下才能設計出aa這樣的遊戲效果。因為插針的起點和終點的計算依賴於圓形的中心到邊界各點的距離相等這一性質,具體可以用如下兩張圖來表示座標點的換算過程:

其中的基準點為在靜止時“針”的插入點(對應於繪製“針”的起點),而終點可以通過相同的方法來實現換算,只不過半徑r的值需要做出相應的調整。

那麼實踐所面臨的問題又轉向了如何取得在旋轉過程中圖層的旋轉角度了,很不幸地說,Apple沒有提供直接的API來擷取這麼一個值。在筆者實踐了一些方法無果後,就決定在Stack Overflow去刷下存在感,問一下問題,結果就遇到了一些尷尬的事情!就把它當做是一個小插曲,分享給各位,望引以為戒!

無疑,在Ask question之前,你得先搜尋相關問題是否有人已經提出,或許你就可以直接撿現成的了。這不,剛輸入關鍵字就發現了可能的解決方案:

看一看問題描述:

看看回答:

咦!好像有那麼一回事,先拿來試下!………………… (此處略去100字的實踐過程)結果發現,它只能計算旋轉最終狀態時的角度值,即如果別人不告訴你某個視圖將要旋轉多少角度,你可以這樣來得到他預先設定值。計算結果顯然是和XXView.transform.b、XXView.transform.a相關的,因為在設定結束後,相應的仿射變換也會隨即生效。

問題沒有得到解決,於是新的問題就有提出來的必要了:

完了之後,就被人“嘲笑”了,這是理由:

這是他把我的問題改版前後的對照結果:

唉!原諒我這個新手的不懂規矩啊!這也從一個側面反映了Stack Overflow的專業性,也就難怪大神們都願意在這裡進行技術交流。下面是我的道謝:

很遺憾,到目前為止還沒有任何人回答這個問題!真是大寫的尷尬啊!所以在遇到問題時,向別人請教的同時自己也需要不斷思考問題的解決方案。正所謂“自己動手,豐衣足食”。

其實,之前的回答已經告訴了我們答案,只是這裡我們需要在動畫過程中通過某種方式來獲得類似於XXView.transform.b、XXView.transform.a這樣的量。我們都知道的是要是涉及到動畫的話,圖層會將動畫的過程交給presentationLayer(表現層)來完成。至於動畫的初值和終值之間的中間值則由系統不斷計算,並通過表現層來展示。說到這裡就很明確了,我們在這裡所涉及到的需求依據變顏色這段文字,所遇到的麻煩就迎刃而解了。

一直向前

既然我們選用的是圖層,我們就需要知道它的transform屬性是一個名為CATransform3D的結構體變數,而XXViewtransform屬性是一個名為CGAffineTransform的結構體變數。前者就自然沒有a、b這樣的成員變數,而是這樣的一個矩陣結構:

struct CATransform3D{  CGFloat m11, m12, m13, m14;             CGFloat m21, m22, m23, m24;  CGFloat m31, m32, m33, m34;  CGFloat m41, m42, m43, m44;};

其中的m14、m24、m34、m44只是作為矩陣的預留位置,通常會將m14、m24、m34設定為0,m44設為1。其他分量的值對應於不同的情境,表示如下:

這個例子中我們是圍繞z軸旋轉的,我們就可以使用反正切變換函數參入實際參數m21、m22的值就可以即時地知道圖層的當前旋轉角度了,不過這肯定需要一些修正以適配於順時針、逆時針的角度計算結果範圍為0 ~ 2π(反正切計算結果以弧度製表示):

//此方法為對外開放的方法,主要用於在不同旋轉方向下,能夠即時擷取圖層的旋轉角度- (CGFloat)transformAngleWithRotationDirection:(BOOL)clockwise {    return clockwise ? [self transformRotationAngle] : 2.0f * M_PI - [self transformRotationAngle];}//此方法為私人方法,它所返回的值對於座標變換計算有直接使用之便- (CGFloat)transformRotationAngle {    //這裡其實可以用反正弦和反餘弦來計算角度值    CGFloat degreeAngle = - atan2f(self.presentationLayer.transform.m21, self.presentationLayer.transform.m22);    if (degreeAngle < 0.0f) {        degreeAngle += (2.0f * M_PI);    }    return degreeAngle;}

藉助於數學誘導公式,座標的變換計算公式可以統一為如下形式:

- (CGPoint)convertPointWhenRotatingWithBenchmarkPoint:(CGPoint)point roundRadius:(CGFloat)radius {    CGFloat rotationAngle = [self.presentationLayer transformRotationAngle];    return CGPointMake(point.x + sinf(rotationAngle) * radius, point.y - radius + cosf(rotationAngle) * radius);}

下面是最終的:

總結

雖然,在書寫文章的時候給人的感覺思路是很明確的,且整個過程是連貫的,但是事實上在實踐中走彎路甚至半途而廢是不可避免的。拿這個Demo來說,在這之前動手寫過一次的,但是那次可能因為技術的儲備不夠(到現在為止,網上依然找不到其他人在iOS平台上對這個遊戲的實現Demo),半途而廢了!但就在前幾天,覺得技術提升與否需要通過是否能完成之前不能完成的任務來衡量。加上做別人沒有做過的實踐,總是會更有趣和更有挑戰意義的,這不就是價值的體現嗎?這裡是Demo的,有興趣的朋友可以下載下來看看,謝謝捧場!

iOS平台上aa(見縫插針)遊戲的簡易實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.