【问题标题】:Aligning second sprite to physics body of first sprite in Spritekit/Swift在 Spritekit/Swift 中将第二个精灵与第一个精灵的物理主体对齐
【发布时间】:2017-06-24 04:52:15
【问题描述】:

我有一个带有物理身体的精灵。 为了移动这个精灵,在 update() 函数中,我不断地将精灵的速度设置为向右移动 150 单位,向左移动 -150。 (见附件代码。)

我有第二个物理体,我想跟随第一个精灵。第二个物理体的坐标在第一个的底部,向右 20 个点。

我希望第二个物理体始终跟随第一个物理体,并带有偏移量。

我的代码大部分有效,但我注意到第一个和第二个主体之间的距离略有不同,我希望没有变化。向右移动时,它们之间的距离被压缩了一点。向左移动时,它们之间的距离会增加一点。在此处观看视频:https://www.youtube.com/watch?v=K9FhIdMwp7k

这是我正在使用的代码:

override func update(_ currentTime: TimeInterval) {

    switch playerDirection {
    case "stopped":
        playerSpeed = 0.0
    case "right":
        playerSpeed = 150.0
    case "left":
        playerSpeed = -150.0
    default:
        print("default")
    }

    // ball is the first sprite and footBall is the second sprite:

    ball.physicsBody?.velocity = CGVector(dx: playerSpeed, dy: ball.physicsBody!.velocity.dy)

    footBall.position = CGPoint(x: (ball.position.x + 20), y: ball.position.y - (ball.size.height / 2) + 4)

    myCam.position = CGPoint(x: round(ball.position.x), y: self.size.height / 2)

...

我也一直在尝试使用 override func didSimulatePhysics() 也没有成功。

我做了一个不同的测试,只是不使用速度来移动玩家,而是直接增加 ball.position.x (ball = player) 和 footBall.position.x,当我这样做时,一切都完美对齐.但如果我走这条路,我将不得不改变我的游戏物理在游戏其他地方的工作方式,我宁愿忽略这一点。

感谢观看。

【问题讨论】:

    标签: swift physics


    【解决方案1】:

    如果您将第二个节点添加为第一个节点的子节点,它会满足您的要求吗?也就是说,而不是将两者置于同一级别:

    scene.addChild(ball)
    scene.addChild(footBall)
    

    替换为:

    scene.addChild(ball)
    ball.addChild(footBall)
    

    只需将足球位置设置为您需要的偏移量:

    footBall.position = CGPoint(x: 20, y: - (ball.size.height / 2) + 4)
    

    那么每当球移动时,footBall 也会移动,因为它是一个子节点,因此您可以删除 footBall 的手动位置更新代码。

    【讨论】:

    • 这种东西非常适合将精灵添加到另一个精灵,但它不适用于物理实体。我刚刚找到了一个可以接受的解决方案,即使用 SKPhysicsJoint developer.apple.com/reference/spritekit/skphysicsjoint 。但是我仍然不知道为什么我的原始帖子中存在可变的“压缩/扩展”差距。也许有一天我会弄清楚为什么会这样。
    • 感谢您的回复 :)
    【解决方案2】:

    我使用 SKPhysicsJoint 来解决这个问题。这是我的工作代码(此时正在测试,所以仍然有点草率,但它在原则上有效):

        //add a nice player
        ball = SKSpriteNode(texture:spriteArray2[0])
        ball.size = CGSize(width: 150, height: 48)
        //ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 2)
        ball.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 16, height: 48))
        ball.zPosition = 1
        ball.physicsBody?.affectedByGravity = true
        ball.position = CGPoint(x: 80.0, y: 200.0)
        ball.physicsBody?.categoryBitMask = 1
        ball.physicsBody?.collisionBitMask = UInt32(2 | 32 | 256) //2 = floors, 32 and 256= doors.
        ball.physicsBody?.contactTestBitMask = 0
        ball.physicsBody?.isDynamic = true
        ball.physicsBody?.restitution = 0.0
        ball.physicsBody?.allowsRotation = false
        ball.physicsBody?.mass = 60.0
        ball.physicsBody?.friction = 0.00
        addChild(ball)
    
        //add a nice ball for when jumping
        footBall = SKSpriteNode(color: SKColor.blue, size: CGSize(width: 24, height: 16))
        footBall.position = ball.position
        footBall.name = "footBall"
        footBall.zPosition = 1
        footBall.physicsBody = SKPhysicsBody(circleOfRadius: 4)
        footBall.physicsBody?.affectedByGravity = false
        footBall.physicsBody?.categoryBitMask = 16
        footBall.physicsBody?.collisionBitMask = 2 // floors
        footBall.physicsBody?.contactTestBitMask = UInt32(32 | 64 | 128 | 256) // the doors bear snake
        footBall.physicsBody?.isDynamic = true
        footBall.physicsBody?.restitution = 0.0
        //footBall.physicsBody?.allowsRotation = false
        //footBall.physicsBody?.mass = 60.0
        //footBall.physicsBody?.friction = 0.00
        addChild(footBall)
    
        let myCGPoint = ball.position // sets joint position
    
        let myJoint = SKPhysicsJointFixed.joint(withBodyA: ball.physicsBody!, bodyB: footBall.physicsBody!, anchor: myCGPoint)
    
        scene?.physicsWorld.add(myJoint)
    

    ...

    然后在更新循环中我为播放器设置速度:

        ball.physicsBody?.velocity = CGVector(dx: playerSpeed, dy: ball.physicsBody!.velocity.dy)
    

    在我的原始代码中,在我的更新循环中,我还根据需要调整了足球的位置以匹配球(球员)的位置,但在修改后的代码中,由于使用了关节,通过移动足球与它一起移动,无需以其他方式施加任何力或速度或更改足球的 x 位置。足球只是跟随骑行,这很有效。

    起初,这个新方法不能正常工作,我通过反复试验发现原因是“footBall.physicsBody?.allowsRotation = false”不能指定为footBall上的属性。但是,通过取消注释此行,它可以正常工作。

    本练习的重点是使用足球作为跳跃测试点,以测试球员在跳跃过程中双脚是否伸直。因此,足球在主球员身体的稍微靠前。然后我会根据跳跃的需要动态地打开或关闭这个足球。

    与“足部传感器”有关的以下页面有些相关: http://gamedevwithoutacause.com/?p=1076 http://www.iforce2d.net/b2dtut/jumpability

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多