Как обнаружить касание на узле
У меня есть приложение, которое порождает мяч на экране каждую 1 секунду. Теперь я хочу, чтобы пользователь коснулся этих шариков, что заставляет их исчезать (removeFromParent()). как я понимаю, я должен установить функцию касания через touchesBegan, и я делаю так, вот мой код:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
let positionOfTouch = touch.location(in: self)
enumerateChildNodes(withName: "BALL") { (node: SKNode, nil) in
if positionOfTouch == node.position {
print("just touched the ball")
}
else{
print("error")
}
}
}
проблема в том, что когда я касаюсь экрана / шара, ошибка печати консоли вместо того, чтобы просто касаться шара, означает, что мой код не работает. Более того, на консоли выводится сообщение об ошибке в виде количества шаров на мой взгляд. я не понимаю, что я делаю неправильно и как на самом деле установить эту функцию. вот моя функция createBall, которая реализуется из моего класса BallNode (типа SKShapeNode):
func createBall(){
let ball = BallNode(radius: 65)
print(ball.Name)
print(ball._subName!)
ball.position.y = ((frame.size.height) - 200)
let ballXPosition = arc4random_uniform(UInt32(frame.size.width)) // set the ball a randon position from the top of the screen
ball.position.x = CGFloat(ballXPosition)
ball.physicsBody?.categoryBitMask = PhysicsCategory.ball // ball's category bitMask
ball.physicsBody?.collisionBitMask = PhysicsCategory.ball // prevent objects from intersecting
ball.physicsBody?.contactTestBitMask = PhysicsCategory.topBorder // when need to know if two objects touch each other
addChild(ball)
}
ты можешь мне помочь с этим? поскольку я совсем новичок в swift, я также хотел бы получить некоторое объяснение об этом обнаружении касания (и касаний в целом - плохой документ Apple).
3 ответа
Каждый раз, когда вы касаетесь экрана, вы перебираете все шары, чтобы увидеть, касаетесь ли вы одного из них. если у вас есть 50 шаров на экране, он просматривает их все, чтобы увидеть, касаетесь ли вы 1. Это не эффективный способ выяснить, касаетесь ли вы 1.
Есть много способов сделать это, но я бы обработал прикосновения внутри класса Ball. Таким образом, вам не нужно выяснять, касаетесь ли вы мяча и каким он может быть.
Объяснение протокола (насколько мне известно) это может показаться немного сложным прямо сейчас, но чем быстрее вы будете изучать и понимать протоколы, тем лучше вы будете (IMO).
В этом примере мы будем использовать протокол для настройки делегата класса BallNode. Протокол - это набор определенных пользователем "правил", которым должен следовать любой класс, который вы определили как соответствующий этому протоколу. В моем примере я утверждаю, что для того, чтобы класс был совместим с протоколом BallNodeDelegate, он должен содержать функцию didClick. Когда вы добавляете BallNodeDelegate после GameScene, вы заявляете, что этот класс будет совместим с этим протоколом. Так что если в GameScene у вас не было функции didClick, это вызовет ошибку. Все это реализовано так, чтобы у вас был простой способ связи между вашими экземплярами BallNode и вашим классом GameScene (без необходимости передавать ссылки на ваш GameScene каждому BallNode). Каждый BallNode имеет делегата (GameScene), которому вы можете передать информацию.
внутри вашего класса BallNode убедитесь, что у вас есть isUserInteraction = true
вне вашего класса BallNode создайте протокол, который отправит сенсорную информацию обратно в GameScene
protocol BallNodeDelegate: class {
func didClick(ball: BallNode)
}
создать переменную делегата в вашем классе BallNode
weak var delegate: BallNodeDelegate!
переместить штрихи начали к вам класс BallNode
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.delegate?.didClick(ball: self)
}
в GameScene добавьте соответствие протоколу BallNode
class GameScene: SKScene, BallNodeDelegate
в GameScene при создании Ball убедитесь, что вы установили его делегат
let ball = BallNode()
ball.delegate = self
в GameScene добавьте гнездо. функция для обработки кликов
func didClick(ball: BallNode) {
print("clicked ball")
}
Вы сравниваете точную точку касания с точным положением узла, которые вряд ли когда-либо будут одинаковыми.
if positionOfTouch == node.position {
Вместо этого вам нужно проверить, достаточно ли близко касание пользователя к позиции мяча.
Одним из вариантов является использование SKNode
"s contains
функция, которая будет обрабатывать это для вас.
if node.contains(positionOfTouch) {
Примечание: вы, вероятно, захотите использовать SKSpriteNode
вместо SKShapeNode
, как SKShapeNode
имеет плохую производительность в SpriteKit.