Измените SKSpriteNode.isHidden на false при попадании в raycast, в противном случае установите значение true - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь создать линию обзора / поле обзора в 2d игре, и у меня возникли некоторые проблемы.В настоящее время я пытаюсь использовать Raycast в качестве решения.Идея в том, что по умолчанию все мои вражеские узлы имеют isHidden = true.Когда лучевая трансляция попадает в них, она должна изменить это значение на false, а когда лучевая трансляция больше не попадает на них, она должна изменить его обратно на true.

Я перепутался с большим количеством различныхварианты тут.Я попытался отследить переменную попадания raycast, как предложено здесь .

В настоящее время я настроил его в операторе if-else, чтобы обработать его, но в результате этого вспыхивают спрайтывход и выход, если лучевая передача ударила, и затем уйдет isHidden = false, если это было истинно изначально.

 scene?.physicsWorld.enumerateBodies(alongRayStart: rayStart, end: rayEnd) { (body, point, normal, stop) in
    let sprite = body.node as? SKSpriteNode
    if body.categoryBitMask == 2 {
        sprite?.isHidden = true
    }else if body.categoryBitMask == 1 {

    } else { sprite?.isHidden = true }
}

У меня есть приведенный выше код как часть функции, которую я затем вызываю в функции update ().

Я ожидаю, что спрайт будет иметь значение только isHidden = falseкогда в настоящее время поражен Raycast.К сожалению, это не работает таким образом.

Ответы [ 2 ]

1 голос
/ 27 марта 2019

Я бы сначала поместил всех своих врагов в специальный контейнер узлов на сцене, а затем, перед тем как наложить луч, сбросил свойство врагов isHidden, используя forloop.

enemyContainer.children.forEach{$0.isHidden = false}
scene?.physicsWorld.enumerateBodies(alongRayStart: rayStart, end: rayEnd) { (body, point, normal, stop) in
    if let sprite = body.node as? SKSpriteNode,sprite.categoryBitMask & ~0b1 \\Replace 0b1 with your category bit mask constant if you created one
        sprite.isHidden = true
    }
}

Это позволит вам сразу выяснить, касается ли свет врага, в отличие от ответа E.Coms, который будет сообщать вам только о том, когда враг попал в фазу обновления физики

если вы не хотите, чтобы ваши враги находились в специальном контейнере, тогда вы можете создать массив и хранить только те, которые были затронуты в последний раз, когда был наложен луч

//Global to class
var nodesInLight = [SKNode]()

.......

//in func

nodesInLight.forEach{$0.isHidden = false}
nodesInLight = [SKNode]() //Allow ARC to remove the previous container, instead of calling clear on it
scene?.physicsWorld.enumerateBodies(alongRayStart: rayStart, end: rayEnd) { (body, point, normal, stop) in
    if let sprite = body.node as? SKSpriteNode,sprite.categoryBitMask & ~0b1 \\Replace 0b1 with your category bit mask constant if you created one
        sprite.isHidden = true
        nodesInLight.append(sprite)
    }
}

Продвинутая техника, которую я бы сделал, - это создать массив слабых ссылок, таким образом, вы случайно не создадите цикл сохранения.

0 голосов
/ 27 марта 2019

В этом случае вы можете дать лучу реальное физическое тело и внедрить контактного делегата.В функции DidBegin, чтобы включить врага.и DidEnd func, выключите врага.

func didBegin(_ contact: SKPhysicsContact) {
    print("begin")

}

func didEnd(_ contact: SKPhysicsContact) {
     print("end")
}

override func didMove(to view: SKView) {
    view.showsPhysics = true

    let ray = SKShapeNode()

    ray.path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 1000, height: 20)).cgPath
    ray.fillColor = UIColor.red
    addChild(ray)
    ray.physicsBody = SKPhysicsBody(rectangleOf:(ray.path?.boundingBoxOfPath)!.size)
    ray.physicsBody?.affectedByGravity = false
    ray.run(SKAction.repeatForever(SKAction.rotate(byAngle: CGFloat(Float.pi * 2), duration: 3)))
    ray.physicsBody?.contactTestBitMask = 1
      ray.physicsBody?.collisionBitMask = 0

    let enemy = SKSpriteNode(color: UIColor.green, size: CGSize.init(width: 100, height: 100))
     enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.frame.size)
     enemy.physicsBody?.affectedByGravity = false
     enemy.position = CGPoint(x: 200, y: 200)
     enemy.physicsBody?.contactTestBitMask = 1
     enemy.physicsBody?.collisionBitMask = 0
     addChild(enemy)
     enemy.isHidden = true
     physicsWorld.contactDelegate = self
...