简体   繁体   English

如何在 Swift 4.2 SpriteKit 中让子节点跟随父节点

[英]How to make child node follow parent node in Swift 4.2 SpriteKit

I want to make it so that a child sprite follows its corresponding parent sprite.我想让它使子精灵跟随其相应的父精灵。 The child sprite has a physics body which should not mess with the parent's physics body.子精灵有一个物理体,它不应该与父级的物理体混淆。 I have tried to in the parent sprite's subclass to override these functions like this:我试图在父精灵的子类中像这样覆盖这些函数:

public override func run(_ action: SKAction) {
    super.run(action)
    physicsSprite.run(action)
}
public override func run(_ action: SKAction, withKey key: String) {
    super.run(action, withKey: key)
    physicsSprite.run(action, withKey: key)
}
public override func removeAllActions() {
    super.removeAllActions()
    physicsSprite.removeAllActions()
}

with no success however :(然而没有成功:(
I'am exclusively moving the parent sprite with SKActions.我专门用 SKActions 移动父精灵。 The result is that the sprites don't stick together.结果是精灵不会粘在一起。

physicsSprite.zPosition = 10
physicsSprite.physicsBody = SKPhysicsBody(circleOfRadius: playerInfo.width+2)
physicsSprite.physicsBody?.affectedByGravity = false
physicsSprite.physicsBody?.isDynamic = false
physicsSprite.physicsBody?.restitution = 0
physicsSprite.physicsBody?.collisionBitMask = 0
addChild(physicsSprite)

In this case physicsSprite is the childNode in a SKSpriteNode subclass.在这种情况下,physicsSprite 是 SKSpriteNode 子类中的 childNode。 Thanks in advance提前致谢

Lots of ways to do this. 有很多方法可以做到这一点。 Comparing the positions of the nodes (leader/follower) on a regular basis and updating the positions accordingly should work. 定期比较节点(领导者/跟随者)的位置并相应地更新位置。 Example: leader goes to some positions > positions do not match > move the follower to the location of the leader. 示例:领导者转到某些位置>位置不匹配>将跟随者移动到领导者的位置。

Code example 代码示例

class GameScene: SKScene {
    private var leader: SKSpriteNode!
    private var follower: SKSpriteNode!

    override func didMove(to view: SKView) {
        self.leader = SKSpriteNode(color: UIColor.red, size: CGSize(width: 30, height: 30))
        self.follower = SKSpriteNode(color: UIColor.green, size: CGSize(width: 30, height: 30))
        self.addChild(leader)
        self.addChild(follower)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches {
            let target = t.location(in: self)
            // Move the leader to the touch location
            leader.run(SKAction.move(to: target, duration: 1), withKey: "moving")
        }
    }

    override func update(_ currentTime: TimeInterval) {
        // Check positions
        if follower.position != leader.position {
            // Check if the follower has a 'following' action already
            if follower.action(forKey: "following") == nil {
                // Move the follower
                follower.run(SKAction.move(to: leader.position, duration: 1), withKey: "following")
            }
        }
    }
}

Note that the update action is called once per frame, which may be too much. 请注意,每帧调用一次更新操作,这可能太多了。 Depending on your situation, you could create some kind of cycle that is called every second. 根据您的情况,您可以创建一种每秒调用一次的循环。

Another way would be to always run the same action on the following node (possibly with a longer duration, such that you can actually see the following node). 另一种方法是始终在下一个节点上运行相同的操作(可能持续时间更长,这样您就可以实际看到下一个节点)。

Edit: More about collisions: Can't understand how collision bit mask works (just make sure they have different contact bit masks - ie. 0b01 and 0b10 and are not in each others collision bit mask) 编辑:有关冲突的更多信息: 无法理解冲突位掩码的工作原理 (仅确保它们具有不同的接触位掩码-即0b01和0b10且彼此之间不在冲突位掩码中)

You could try to use an SKConstraint object, that describes a mathematical constraint on a node's position or orientation.您可以尝试使用SKConstraint对象,它描述了对节点位置或方向的数学约束。

From the docs:从文档:

Keep a node within a specified distance of another node or a point in the scene.将节点保持在与另一个节点或场景中的点的指定距离内。

See https://developer.apple.com/documentation/spritekit/skconstraint请参阅https://developer.apple.com/documentation/spritekit/skconstraint

Try this:尝试这个:

parentSprite.physicsBody?.categoryBitMask = 0
parentSprite.physicsBody?.collisionBitMask = 0

physicsSprite.physicsBody?.collisionBitMask = 1
physicsSprite.physicsBody?.categoryBitMask = 1

For more information check documentation有关更多信息,请查看文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM