SpriteKit - 實做虛擬搖桿

本文适合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

来吧!第一步!两个圆形!

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

Simulator Screen Shot

组件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只判断是否手指在外圈内,而忽略了若是使用者从内圈滑到外圈的情况。

paddleerroe

让我们把上面那段注解换成

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出去给委任,以便使用者能随着滑动摇杆,做出适当的回应。

paddleError.gif

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×