как обнаружить прикосновение к узлу

У меня есть приложение, которое запускает мяч на экране каждые 1 секунду. теперь я хочу, чтобы пользователь коснулся тех шаров, из-за чего они исчезли (removeFromParent()). как я понимаю, мне нужно установить функцию касания через touchhesBegan, и я это сделаю, вот мой код:

    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 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)

}

Можете ли вы мне помочь? потому что я брошу новое для быстрого, я также хотел бы получить некоторое объяснение об этом обнаружении касания (и касается вообще - яблочный документ плохой).

+1
источник поделиться
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 class

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 для обработки кликов

func didClick(ball: BallNode) {
    print("clicked ball")
}
+2
источник

Вы сравниваете точную точку касания с точным положением узла, которые вряд ли когда-либо будут одинаковыми.

if positionOfTouch == node.position {

Вместо этого вам нужно будет проверить, достаточно ли близко касаться пользователя до положения мяча.

Одним из вариантов является использование SKNode contains функцию, которая будет обрабатывать это для вас.

if node.contains(positionOfTouch) {

Боковое примечание. Вероятно, вы захотите использовать SKSpriteNode вместо SKShapeNode, так как SKShapeNode имеет низкую производительность в SpriteKit.

+1
источник

Взгляните на nodes(at:CGPoint) определенные на SKNode чтобы получить список узлов в затронутой позиции. Вам нужно будет преобразовать между координатами представления и координатами сцены, хотя, используя convertPoint(fromView). Документация здесь и здесь.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос