SKScene - Как получить класс от SKSpriteNode - PullRequest
0 голосов
/ 23 января 2020

Я использую spritekit для создания сцены. У меня есть 3 класса: GameScene, Bullet и Enemy. В моей GameScene я добавил создать SKSpriteNode через мои классы Bullet и Enemy.

var newBullet = Bullet(); 
newBullet.CreateBullet()
self.addChild(newBullet.GetSpriteNode())

Позже я использую обнаружение столкновений, расширяя SKPhysicsContactDelegate.

func didBegin(_ contact: SKPhysicsContact) {
    print("collision detected!")
    let firstBody = contact.bodyA.node as! SKSpriteNode;
    let secondBody = contact.bodyB.node as! SKSpriteNode;

    //here's where I'd like to call bullet.hit() 
    //var bullet = firstBody.GetClass(Bullet)
    //bullet.hit()
    // I tried -  let tempBullet = ((firstBody as? Bullet));
    //but firstBody as? Bullet returns nil
    //print(firstBody) - it indeed is my bullet sprite... why is it nil?
}

Я написал свой псевдокод выше ... как бы получить класс, связанный с SKSpriteNode ..? Есть ли способ, чтобы мой сценарий класса был частью SKSpriteNode, и если да - как мне присоединить сценарий для вызова его функций?

Также вот мой класс маркера

class Bullet : SKSpriteNode{
   var skNode : SKSpriteNode?

   func CreateBullet(){
        skNode = SKSpriteNode(color: SKColor.white, size: CGSize(width: 2, height: 10))
        skNode?.name = "bullet"
        skNode?.position = CGPoint(x: 0, y: 0)

        skNode?.physicsBody = SKPhysicsBody(rectangleOf: skNode!.size)

        skNode?.physicsBody?.isDynamic = true;
        skNode?.physicsBody?.allowsRotation = false;
        skNode?.physicsBody?.pinned = false;
        skNode?.physicsBody?.affectedByGravity = false;

        skNode?.physicsBody?.categoryBitMask = PhysicsCategory.Bullet;
        skNode?.physicsBody?.collisionBitMask = PhysicsCategory.Enemy;
        skNode?.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy;
    }

    func GetSKNode() -> SKNode{
        return skNode!;
    }
}

1 Ответ

1 голос
/ 25 января 2020

Не уверен, почему вы создаете пулю так, как вы делаете. Я думаю, что это должно выглядеть больше по линии. При создании подкласса SKSpriteNode вы должны переопределить инициализатор, чтобы добавить свои собственные настройки.

class Bullet: SKSpriteNode {

    init() {
        let size = CGSize(width: 2, height: 10)
        super.init(texture: nil, color: .white, size: size)
        self.name = "bullet"
        self._setupBody(size: size)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    //Prefix private methods with an underscore
    private func _setupBody(size: CGSize) {
        self.physicsBody = SKPhysicsBody(rectangleOf: size)
        self.physicsBody?.isDynamic = true
        self.physicsBody?.allowsRotation = false
        self.physicsBody?.pinned = false
        self.physicsBody?.affectedByGravity = false
        self.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
        self.physicsBody?.collisionBitMask = PhysicsCategory.Enemy
        self.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
    }

}

Причина, по которой при попытке приведения в качестве Bullet создается ноль, заключается в том, что вы создаете SKSpriteNode при вызове newBullet.CreateBullet() вместо экземпляра класса Bullet.

Наконец, в физикаКонтакт, в контакте два тела. Мы не знаем, кто враг, а кто пуля. Таким образом, мы можем написать код для обоих случаев, хотя, если вы проверяете больше коллизий, есть лучшие способы, такие как этот ответ: Определение тел контакта

class BulletScene:SKScene, SKPhysicsContactDelegate {


    func didBegin(_ contact: SKPhysicsContact) {

        //Case #1: Bullet = bodyA and Enemy = bodyB
        if let bullet = contact.bodyA.node as? Bullet, let enemy = contact.bodyB as? Enemy {
            print("Bullet was BodyA!")
        //Case #2: Bullet = bodyB and Enemy = bodyA
        }else if let enemy = contact.bodyA as? Enemy, let bullet = contact.bodyB.node as? Bullet {
            print("Bullet was BodyB!")
        }
    }


} 
...