SKPhysicsContactDelegate обнаружение столкновений с помощью Swift
Я пытаюсь решить проблему с обнаружением столкновений SKPhysicsContactDelegate. У меня есть два узла, узел A и узел B, узел A находится на экране неподвижно, в то время как узел B может перемещаться по экрану пальцем пользователя. узел A должен иметь возможность определять, перекрывает ли его узел B. Методы didBeginContact и didEndContact вызываются несколько раз, что в ходе исследований я обнаружил, что это ожидаемое поведение. Чтобы обойти эту проблему, я просто установил целочисленную переменную в 0 и увеличивал ее каждый раз, когда был контакт, и уменьшал ее каждый раз, когда контакт заканчивался. Если значение больше 0, тогда два узла перекрываются, а если значение равно 0, то это не так. Это работает нормально, пока пользователь не перетаскивает узел B на узел A слишком быстро. Когда это происходит, методы контакта не всегда вызываются в правильное количество раз. Например, может быть обнаружено 3 контакта, но только два конечных контакта (или даже ни одного), что заставляет программу думать, что эти два узла по-прежнему перекрываются, даже если это не так. Я предполагаю, что это происходит потому, что пользователь перетаскивает узел быстрее, чем может обновить программа. Что я могу сделать, чтобы обойти это? В основном мне просто нужно точно знать, когда два узла перекрываются, а когда нет. Также обратите внимание, что узлы имеют выпуклую форму. Ниже приведены мои методы контакта:
func didBeginContact(contact: SKPhysicsContact)
{
let contactMask = contact.bodyA.categoryBitMask + contact.bodyB.categoryBitMask
if contactMask == 3
{
startContact++
timerStart = true
}
}
func didEndContact(contact: SKPhysicsContact)
{
let contactMask = contact.bodyA.categoryBitMask + contact.bodyB.categoryBitMask
if contactMask == 3
{
startContact--
if startContact == 0
{
timerStart = false
}
}
}
1 ответ
Вы можете проверить, пересекается ли один узел с другим, используя метод intersectsNode:. Из документов об этом методе:
Возвращает логическое значение, которое указывает, пересекает ли этот узел указанный узел.
Также важно помнить:
Считается, что два узла пересекаются, если их кадры пересекаются. Дочерние элементы обоих узлов игнорируются в этом тесте.
import SpriteKit
class GameScene: SKScene {
var stationaryNode :SKSpriteNode = SKSpriteNode(color: SKColor.grayColor(), size: CGSize(width: 100, height: 100))
var moveableNode :SKSpriteNode = SKSpriteNode(color: SKColor.purpleColor(), size: CGSize(width: 100, height: 100))
let debugLabel :SKLabelNode = SKLabelNode(fontNamed: "ArialMT")
override func didMoveToView(view: SKView) {
setupScene()
}
func setupScene(){
stationaryNode.name = "stationaryNode"
stationaryNode.zRotation = 0.2
stationaryNode.zPosition = 1
stationaryNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
addChild(stationaryNode)
moveableNode.name = "moveableNode"
moveableNode.zRotation = 0.4
moveableNode.zPosition = 2
moveableNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)-200)
addChild(moveableNode)
debugLabel.fontSize = 18
debugLabel.fontColor = SKColor.yellowColor()
debugLabel.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)+200)
addChild(debugLabel)
updateDebugLabel()
}
func updateDebugLabel(){
let intersectionDetected:String = stationaryNode.intersectsNode(moveableNode) ? "YES" : "NO"
debugLabel.text = "Overlapping : " + intersectionDetected
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let previousPosition = touch.previousLocationInNode(self)
let node: SKNode? = nodeAtPoint(location)
if let nodeName = node?.name{
if nodeName == "moveableNode" {
let translation = CGPoint(x: location.x - previousPosition.x , y: location.y - previousPosition.y )
node!.position = CGPoint(x: node!.position.x + translation.x, y: node!.position.y + translation.y)
}
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
updateDebugLabel()
}
}
Я думаю, что это решение работает немного лучше, чем при использовании физического движка для обнаружения контактов для таких быстро движущихся объектов. Тем не менее, очень быстрое перемещение объекта может привести к непредсказуемому результату.