SpriteKit遊戲開發點滴[5]旋轉 & Anchorpoint,spritekit遊戲開發
最近在做關於旋轉的動畫效果,遇到了些問題,在解決問題的過程中對SpriteKit中的旋轉有所更加深入的瞭解,在此進行個總結。
我想實現下面的這個效果:一個水管繞著白色星球的中心進行旋轉。
最自然的想法是直接使用SpriteKit的SKAction.rotateByAngle方法直接進行旋轉即可。
那麼問題來了,一個SKSpriteNode元素如何繞一個指定的點旋轉呢?
預設情況下,每個SKSpriteNode節點都有一個錨點(Anchorpoint),而rotateByAngle方法則是以錨點為中心進行旋轉。
比如當錨點為螢幕中心時:
比如錨點為螢幕左下角時:
那麼,就將水管的Anchorpoint設定為白色星球的圓心位置即可。(修改Anchorpoint不是好辦法)
但是,Anchorpoint預設是(0.5,0.5),為水管元素的中心點,它是代表相對於SKSpriteNode的比例的位置。
為什麼Anchorpoint不能直接設定為固定的像素點位置呢?這樣不是更簡單更方便易用?
因為錨點實際上是元素的“抽象點”,而元素的位置(position)是該錨點的位置,往往該抽象點位於元素的內部。
在用rotateByAngle方法進行旋轉時,物體雖然繞著錨點進行旋轉,但是因為錨點並沒有移動,所以物體的位置(Position)始終沒有發生改變,改變的是ZRotation
舉個栗子:
圖中藍色的邊框代表物理引擎計算得到的碰撞形狀,白色邊框代表SKSpriteNode的frame,藍色小人的中心為汽車錨點的位置。
很顯然的,這裡汽車的錨點被為(0,0)。
但是對於物理碰撞形狀,它的錨點並沒有隨汽車的錨點改變而改變(也就是說如果修改了SKSpriteNode的錨點,在使用物理引擎時就會出現偏差,或許這是目前的版本SpriteKit的bug吧)。
那麼,如果既想使用預設的物理引擎進行碰撞檢測並對物體施力,又想讓物體繞著給定的一點進行旋轉?該如何做呢?
也就是說如何在不修改Anchorpoint的情況下,讓物體繞給定的點進行旋轉?
很簡單,手工修改物體的position和ZRotation即可。
假設物體為element,繞點point旋轉rad弧度每幀,則可以在每次更新時調用方法:
(具體的點A繞點B旋轉rad的計算參看點擊開啟連結)
func rotateByPoint(element:SKNode,point:CGPoint,rad:CGFloat) { let tempPos = element.position let resultX = point.x + (tempPos.x - point.x) * cos(rad) - (tempPos.y - point.y) * sin(rad) let resultY = point.y + (tempPos.x - point.x) * sin(rad) + (tempPos.y - point.y) * cos(rad) //修改角度 element.zRotation += rad //修改位置 element.position.x = resultX element.position.y = resultY }
如果簡單些,繞給定點旋轉的效果僅僅是為了好看,沒有和其他元素進行什麼互動的話(或者僅僅是粗略地通過frame是否重疊進行碰撞判斷)
可以考慮修改Anchorpoint,進行實現。
具體做法是:
添加一個父親節點,將其position設定為旋轉被繞的點的位置;
然後將物體的位置設為相對父節點的新座標;
直接對父親節點進行rotateByAngle即可。
總的來說,Anchorpoint是為了“固定”物體到固定的position上而存在,如果想要讓物體繞某任意一點旋轉,並且不影響物理引擎的使用的話,應該考慮修改物體的position和ZRotation的方案。
這個方案應該是可以寫成擴充的SKAction的,不過目前我對SKAction的機制還沒有深入的掌握,爭取在後面將其封裝到SKAction中。
[目前我剛剛開始接觸SpriteKit,經驗還不夠豐富,如果有錯誤還請大家及時指出。]