使 SKPhysicsBody 单向
make SKPhysicsBody unidirectional
我有一个 SKSpriteNode
作为一个球,它被赋予了所有 SKPhysicsBody
属性,可以在各个方向移动。我现在想要的是让它 unidirectional
(只朝它之前没有移动过的方向移动,而不是回到它已经移动过的路径)。目前我对这个问题有以下想法,
- 做一个
fieldBitMask
,到它迭代的路径,并排斥 球回不去了 - 对来自
touchesBegan/ touchesMoved
的球应用某种force/ impulses
方法以防止它返回 - 可以用
update
方法处理的东西 - 来自 stackflowoverflow 的救星,他甚至在周末都在编码 :)
支持代码片段以便更好地理解,
//getting current touch position by using UIEvent methods
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {return}
let location = touch.location(in: self)
lastTouchPoint = location
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {return}
let location = touch.location(in: self)
lastTouchPoint = location
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
lastTouchPoint = nil
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
lastTouchPoint = nil
}
//ball created
func createPlayer(){
player = SKSpriteNode(imageNamed: "player")
player.position = CGPoint(x: 220, y: 420)
player.zPosition = 1
//physics for ball
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
player.physicsBody?.allowsRotation = false
player.physicsBody?.linearDamping = 0.5
player.physicsBody?.categoryBitMask = collisionTypes.player.rawValue
player.physicsBody?.contactTestBitMask = collisionTypes.finish.rawValue
player.physicsBody?.collisionBitMask = collisionTypes.wall.rawValue
addChild(player)
}
//unwarp the optional property, calclulate the postion between player touch and current ball position
override func update(_ currentTime: TimeInterval) {
guard isGameOver == false else { return }
if let lastTouchPosition = lastTouchPoint {
//this usually gives a large value (related to screen size of the device) so /100 to normalize it
let diff = CGPoint(x: lastTouchPosition.x - player.position.x, y: lastTouchPosition.y - player.position.y)
physicsWorld.gravity = CGVector(dx: diff.x/100, dy: diff.y/100)
}
}
好吧,它是 touchesBegan/ touchesMoved
和 update
函数的组合,
首先你需要知道发生了什么触摸,得到它的名字(在我的
案例我制作了 alpha 为 0 的节点,但在
在它们上面移动,即 alpha 1)。在touchesBegan, touchesMoved
如下
guard let touch = touches.first else {return}
let location = touch.location(in: self)
lastTouchPoint = location
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name
{
if name == "vortex"
{
touching = false
self.view!.isUserInteractionEnabled = false
print("Touched on the interacted node")
}else{
self.view!.isUserInteractionEnabled = true
touching = true
}
}
}
其次使用BOOL touching
跟踪用户交互,在屏幕上使用获取点击识别器设置,如下
func setupTapDetection() {
let t = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
view?.addGestureRecognizer(t)
}
@objc func tapped(_ tap: UITapGestureRecognizer) {
touching = true
}
最后在update
中进行如下检查,
guard isGameOver == false else { return }
self.view!.isUserInteractionEnabled = true
if(touching ?? true){
if let lastTouchPosition = lastTouchPoint {
//this usually gives a large value (related to screen size of the device) so /100 to normalize it
let diff = CGPoint(x: lastTouchPosition.x - player.position.x, y: lastTouchPosition.y - player.position.y)
physicsWorld.gravity = CGVector(dx: diff.x/100, dy: diff.y/100)
}
}
}