本文适合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会快上许多,看它的建构值就能知道,真的很“几何”。
来吧!第一步!两个圆形!
1 2 3 4 5
| 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
|
组件2:点击、滑动
Hmm…. We almost here, right? 不过现在你不管怎么拨弄它,它都不会移动的,在SpriteKit里常做的处理点击方式是实作覆写UIResponder大家常见的Method。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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只判断是否手指在外圈内,而忽略了若是使用者从内圈滑到外圈的情况。
让我们把上面那段注解换成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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出去给委任,以便使用者能随着滑动摇杆,做出适当的回应。