【问题标题】:SpriteKit: cannot change node position in contact callbackSpriteKit:无法在联系人回调中更改节点位置
【发布时间】:2014-04-02 11:38:52
【问题描述】:

我有一个带有动态物理体的节点。我想让它静止并在它与另一个身体接触时改变它的位置。

我设法使用此问题中提供的解决方案使正文保持静态:Sprite Kit failing assertion: (typeA == b2_dynamicBody || typeB == b2_dynamicBody)

但是,如果我在其中一种联系回调方法(例如 didBeginContact)中更改节点的 position 属性,则不会考虑新位置。

我怎样才能做到这一点?

【问题讨论】:

  • 能否贴出无法更新位置的代码,以及您如何实现链接到的解决方案?
  • @LearnCocos2D JKallio 给出的解决方案工作正常(将physicsBody 重新分配给它的节点)

标签: sprite-kit


【解决方案1】:

我相信这是 SpriteKit 中的一个错误。 (我能够用 SpriteKit 7.1 重现这个问题)。

这是一个快速的解决方法:

- (void) didBeginContact:(SKPhysicsContact *)contact
{
     contact.bodyB.node.position = CGPointMake(newX, newY);
     contact.bodyB.node.physicsBody = contact.bodyB.node.physicsBody; // <-- Add this line
}

【讨论】:

  • 它工作正常。我只是稍微改变了最后一行:contact.bodyB.node.physicsBody = contact.bodyB.node.physicsBody;
【解决方案2】:

JKallio 的解决方案对我不起作用(OS X 10.10.5 上的 Xcode 7.2.1,针对 iOS 8.1)。我发现我可以在update: 方法中更改位置,所以我通过在didBeginContact 中设置一个标志并更改update: 中的位置来解决这个错误。

@implementation GameScene {
    SKNode *_victim;
    CGPoint _target;
}

- (void)didMoveToView:(SKView *)view {
    _victim = nil;
}

- (void)didBeginContact:(SKPhysicsContact *)contact {
    _victim = contact.bodyB.node;
    _target = CGPointMake(newX, newY);
}

- (void)update:(CFTimeInterval)currentTime {
    if (_victim != nil) {
        _victim.position = _target;
        _victim = nil;
    }
}

@end

请注意,_victim 既是节点又是标志。

我的解决方案比 JKallio 的更复杂;在来之前试试那个。

【讨论】:

    【解决方案3】:

    作为解决方法的另一个选项,我改为在 SKSpriteNode 子类中为我想要移动的对象调用一个方法,并传入该主体。位置设置正确。

    /* In GameScene.swift */
    
    func didBegin(_ contact: SKPhysicsContact) {
        let dotBody: SKPhysicsBody
        if contact.bodyA.categoryBitMask == 0b1 {
            dotBody = contact.bodyB
        } else {
            dotBody = contact.bodyA
        }
    
        if let dot = dotBody.node as? Dot {
            dot.move()
        }        
    }
    

    这是 Dot 类:

    import SpriteKit
    class Dot : SKSpriteNode {
        let dotTex = SKTexture(imageNamed: "dot")
        init() {
            super.init(texture: dotTex, color: .clear, size: dotTex.size())
            self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
            self.physicsBody?.categoryBitMask = 0b1 << 1
            self.physicsBody?.contactTestBitMask = 0b1
        }
    
        func move() {
            let reset = SKAction.run {
                self.position.x = 10000
            }
            self.run(reset)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-10
      • 2015-05-30
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多