(iOS)SpriteKit 製作簡易手遊虛擬搖桿(UIKit通用) Double零元件系列

jamesdouble發表於2019-02-28

本文適合SpriteKit初心者 原始碼:https://github.com/jamesdouble/JDGamePaddle

虛擬搖桿


16年,MOBA手遊市場打得可火熱(這裡我們不幫任何遊戲背書),擼瑟如我也是在16年開始玩SpriteKit,也就是蘋果自制的2D遊戲框架。 有玩過MOBA手遊的,一定十分熟悉遊戲裡我們是如何移動主人公的吧?沒玩過的......我們們不囉唆,先上圖。

圖片取自網路

這樣想不起來的也想起來了唄,因為SpriteKit本身並沒有提供像搖桿這樣元件(有提供反而奇怪),為了以防朋友們採坑(也沒有很多坑),我就寫了一個簡易的搖桿Lib,SKScene,SKView(SpriteKit的UIView), UIView皆可直接加上。

簡單的出發


一開始若把問題想得太複雜,那歪路肯定會走的特別的多,我們就照著上面的圖來刻吧,外面一個圓圈,嗯,裡面一個小圓.....好,結束了 ,就從拉出兩個圓來出發吧!!

元件1:SKShapeNode


For SpriteKit初心者: UIKit裡每個元件幾乎都是UIView的子類別,而SpriteKit裡的每個元件幾乎都是SKNode的子類別。

是吧?有錯請指正

那SKShapeNode又是什麼?它是SKNode的子類別,若是你不是要用圖片來初始化一個物件而是純幾何形狀或是線條的話,使用它來做Node會快上許多,看它的建構值就能知道,真的很“幾何”。

https://developer.apple.com/reference/spritekit/skshapenode

來吧!第一步!兩個圓形!

MovingPing = SKShapeNode(circleOfRadius: paddleSize.width * 0.18)
MovingPing?.fillColor = UIColor.black  //內圓黑色實心
PaddleBorder = SKShapeNode(circleOfRadius: paddleSize.width * 0.5 )
PaddleBorder?.fillColor = UIColor.clear //外圓中間空心
PaddleBorder?.strokeColor = UIColor.black
複製程式碼

Simulator Screen Shot

元件2:點選、滑動


Hmm.... We almost here, right? 不過現在你不管怎麼撥弄它,它都不會移動的,在SpriteKit裡常做的處理點選方式是實作覆寫UIResponder大家常見的Method。


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first!
        touching = true
        let position = touch.location(in: self)
        if((PaddleBorder!.contains(position))) //若是手指還在邊界內
        {
            MovingPing?.position = touch.location(in: self) //內圓移到手指位置
        }
        didMove()
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first!
        let postion = touch.location(in: self)
        if((PaddleBorder!.contains(postion)))
        {
            MovingPing?.position = postion
        }
     
        /*
        略
        */
    }
複製程式碼

結束了嗎?執行起來試試吧。看起來聽生硬的對吧,若是有MOBA手遊只做到這邊,主人公一定是腳抽了筋。會發生這樣的杯具是在touchesMoved只判斷是否手指在外圈內,而忽略了若是使用者從內圈滑到外圈的情況。

paddleerroe
讓我們把上面那段註解換成

    else{
            movingpaddleSmoothly(position: postion)
        }
  //算出邊界外手指跟中心連成一線後,跟邊界的交點。
    func movingpaddleSmoothly(position:CGPoint)
    {
        let centerPoint = PaddleBorder!.position
        let radius = self.frame.width * 0.5
        var distance:CGFloat = 0
        let diffx:CGFloat = (centerPoint.x - position.x) * (centerPoint.x - position.x)
        let diffy:CGFloat = (centerPoint.y - position.y) * (centerPoint.y - position.y)
        distance = sqrt(diffx + diffy)
        let ratio:CGFloat = radius/distance
        let newPostition:CGPoint = CGPoint(x: position.x * ratio, y: position.y * ratio)
        MovingPing?.position = newPostition
        
    }
複製程式碼

最後我們再每次移動搖桿時,回傳一個經過正規化的CGVector出去給委任,以便使用者能隨著滑動搖桿,做出適當的迴應。

paddleError.gif

相關文章