В SpriteKit SKPhysicsContactDelegate контакт не определяется

Я пытаюсь запрограммировать игру с помощью Spritekit в Swift. Цель состоит в том, чтобы убежать со своим персонажем от встречных прямоугольников. Сейчас я ошибся с методом SKPhysicsContactDelegate(didBegin()), поэтому контакт фигуры с одним из прямоугольников не распознается. Может ли кто-нибудь помочь мне найти ошибку?

    import SpriteKit

enum bodyType: UInt32 {
    case rechteckRechts = 1
    case rechteckLinks = 2
    case figur = 4
}

class PlayScene: SKScene, SKPhysicsContactDelegate {

    let figur = SKSpriteNode(imageNamed: "Punkt.jpg")

    @objc func addRechteck(){
        let rechteckRechts = SKSpriteNode(imageNamed: "Rechteck.gif")
        rechteckRechts.physicsBody = SKPhysicsBody()
        rechteckRechts.physicsBody?.isDynamic = false
        rechteckRechts.physicsBody?.categoryBitMask = bodyType.rechteckRechts.rawValue

        let rechteckLinks = SKSpriteNode(imageNamed: "Rechteck.gif")
        rechteckLinks.physicsBody = SKPhysicsBody()
        rechteckLinks.physicsBody?.isDynamic = false
        rechteckLinks.physicsBody?.categoryBitMask = bodyType.rechteckLinks.rawValue

        let groesse = arc4random_uniform(5)+1
        print(groesse)

        switch groesse {
        case 1:
            rechteckLinks.xScale = 0.5
            rechteckRechts.xScale = 1.5
        case 2:
            rechteckLinks.xScale = 1.5
            rechteckRechts.xScale = 0.5
        case 3:
            rechteckLinks.xScale = 1
            rechteckRechts.xScale = 1
        case 4:
            rechteckLinks.xScale = 1.25
            rechteckRechts.xScale = 0.75
        case 5:
            rechteckLinks.xScale = 0.75
            rechteckRechts.xScale = 1.25
        default:
            print("Fehler in der Wahrscheinlichkeit!!!")
        }
        rechteckRechts.position = CGPoint(x: frame.minX + (rechteckRechts.size.width / 2), y: frame.maxY)
        rechteckLinks.position = CGPoint(x: frame.maxX - (rechteckLinks.size.width / 2), y: frame.maxY)

        let moveDown = SKAction.moveBy(x: 0, y: -5000, duration: 20.0)
        rechteckLinks.run(moveDown)
        rechteckRechts.run(moveDown)

        self.addChild(rechteckRechts)
        self.addChild(rechteckLinks)
    }

    override func didMove(to view: SKView) {
        physicsWorld.gravity = .zero
        physicsWorld.contactDelegate = self

        figur.xScale = 0.4
        figur.yScale = 0.4
        figur.position = CGPoint(x: frame.midX, y: frame.maxY / 4)
        figur.physicsBody = SKPhysicsBody()
        figur.physicsBody?.isDynamic = false
        figur.physicsBody?.categoryBitMask = bodyType.figur.rawValue
        self.addChild(figur)

        self.backgroundColor = SKColor.white

        let wait1 = SKAction.wait(forDuration: 3)
        let timer = SKAction.repeatForever(SKAction.sequence([wait1, SKAction.run {
            self.addRechteck()
            }]))
        self.run(timer, withKey: "addRechteck")

    }

    func didBegin(_ contact: SKPhysicsContact) {
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

        switch contactMask {
        case bodyType.figur.rawValue | bodyType.rechteckLinks.rawValue:
            print("contact")
        case bodyType.figur.rawValue | bodyType.rechteckRechts.rawValue:
            print("contact")
        default:
            return
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches ){
            let location = touch.location(in: self)
            if figur.contains(location){
                figur.position = location
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches ) {
            let location = touch.location(in: self)
            if figur.contains(location){
                figur.position = location
            }
        }
    }
}

person Xcode    schedule 04.08.2018    source источник
comment
Вы установили свои битовые маски contactTest?   -  person Steve Ives    schedule 05.08.2018
comment
Нет, я не. Как мне это сделать?.   -  person Xcode    schedule 05.08.2018
comment
Хорошо - смотрите мой ответ.   -  person Steve Ives    schedule 05.08.2018


Ответы (1)


Похоже, вы не установили битовые маски Collision и contactTest. Это свойства физического тела. collisionBitMask контролирует, какие объекты отскакивают от каких других объектов. По умолчанию все отскакивает от всего остального.

contactTestBitMask является важным в этой ситуации, так как он контролирует, какие объекты вызывают «didBegin» при контакте с другими объектами. По умолчанию это 0, что означает, что контакты не зарегистрированы. Смотрите мой ответ здесь: https://stackoverflow.com/a/40596890/1430420 для подробного объяснения.

В вашем конкретном примере вы, кажется, хотите знать, когда figur вступает в контакт с rechteckLinks или rechteckRechts, поэтому вы хотели бы следить за contactTestBitMasks:

figur.physicsBody!.cagegoryBitMask = bodyType.figur
figur.physicsBody!.contactTestBitMask = bodyType.rechteckRechts | bodyType.rechteckLinks

Изменить: исправление определения физического тела figurs:

Мы меняем? к ! так что мы получим сбой, если физическое тело не существует. Мы также меняем свойство isDynamic на true, так как физические тела, которые не являются динамическими, не могут регистрировать контакты (я думаю). Это нормально, если остальные 2 не будут динамичными. Мы присваиваем collisionTestBitMask значениям всех категорий, которые мы хотим уведомлять о столкновении с логическим «ИЛИ» вместе:

figur.physicsBody!.isDynamic = true 
figur.physicsBody!.categoryBitMask = bodyType.figur.rawValue
figur.physicsBody!.contactTestBitMask = bodyType.rechteckRechts.rawValue | bodyType.rechteckLinks.rawValue
person Steve Ives    schedule 05.08.2018
comment
это, наверное, звучит очень глупо, но это не работает. возможно ли, чтобы вы дополнили приведенный выше код своим предложением, а затем отправили мне? - person Xcode; 05.08.2018