将第二个精灵与 Spritekit/Swift 中第一个精灵的物理 body 对齐
Aligning second sprite to physics body of first sprite in Spritekit/Swift
我有一个物理精灵 body。
为了移动这个精灵,在 update() 函数中,我不断地将精灵的速度设置为 150 单位向右移动,-150 向左移动。 (见附件代码。)
我有第二个物理 body,我想跟随第一个 sprite。第二个物理的坐标body在第一个物理的底部,向右20点。
我希望第二个物理 body 始终跟随第一个,但有偏移。
我的代码大部分 有效,但我注意到第一个和第二个主体之间的距离略有不同,我希望没有变化。向右移动时,它们之间的距离被压缩了一点。向左移动时,它们之间的距离会增加一点。在此处观看视频: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(球 = 玩家)和 footBall.position.x,当我这样做时,一切都是完美对齐。但是,如果我采用这条路线,我将不得不改变我的游戏物理在游戏其他地方的工作方式,我宁愿忽略它。
感谢观看。
如果将第二个节点添加为第一个节点的子节点,是否满足您的要求?也就是说,而不是让两者处于同一级别:
scene.addChild(ball)
scene.addChild(footBall)
替换为:
scene.addChild(ball)
ball.addChild(footBall)
然后将 footBall 位置设置为您需要的偏移量:
footBall.position = CGPoint(x: 20, y: - (ball.size.height / 2) + 4)
然后任何时候球移动 footBall 也会移动,因为它是一个子节点,因此您可以删除 footBall 的手动位置更新代码。
我使用 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)
在我的原始代码中,在我的更新循环中,我还根据需要调整了 footBall 的位置以匹配球(球员)的位置,但在修改后的代码中,由于使用了关节,通过移动球footBall 随之移动,无需另外施加任何力或速度或改变 footBall 的 x 位置。 footBall 随行随行,效果很好。
起初,这个新方法并没有正常工作,我通过反复试验发现原因是"footBall.physicsBody?.allowsRotation = false"不能在footBall上指定为属性。但是,通过取消注释这一行它可以正常工作。
本练习的重点是使用 footBall 作为跳跃测试点,用于测试球员在跳跃过程中双脚何时伸展。所以 footBall 因此略微领先于主要球员的 body。然后我会根据跳跃的需要动态打开或关闭这个 footBall。
"foot sensor" 上的以下页面有些相关:
http://gamedevwithoutacause.com/?p=1076
http://www.iforce2d.net/b2dtut/jumpability
我有一个物理精灵 body。 为了移动这个精灵,在 update() 函数中,我不断地将精灵的速度设置为 150 单位向右移动,-150 向左移动。 (见附件代码。)
我有第二个物理 body,我想跟随第一个 sprite。第二个物理的坐标body在第一个物理的底部,向右20点。
我希望第二个物理 body 始终跟随第一个,但有偏移。
我的代码大部分 有效,但我注意到第一个和第二个主体之间的距离略有不同,我希望没有变化。向右移动时,它们之间的距离被压缩了一点。向左移动时,它们之间的距离会增加一点。在此处观看视频: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(球 = 玩家)和 footBall.position.x,当我这样做时,一切都是完美对齐。但是,如果我采用这条路线,我将不得不改变我的游戏物理在游戏其他地方的工作方式,我宁愿忽略它。
感谢观看。
如果将第二个节点添加为第一个节点的子节点,是否满足您的要求?也就是说,而不是让两者处于同一级别:
scene.addChild(ball)
scene.addChild(footBall)
替换为:
scene.addChild(ball)
ball.addChild(footBall)
然后将 footBall 位置设置为您需要的偏移量:
footBall.position = CGPoint(x: 20, y: - (ball.size.height / 2) + 4)
然后任何时候球移动 footBall 也会移动,因为它是一个子节点,因此您可以删除 footBall 的手动位置更新代码。
我使用 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)
在我的原始代码中,在我的更新循环中,我还根据需要调整了 footBall 的位置以匹配球(球员)的位置,但在修改后的代码中,由于使用了关节,通过移动球footBall 随之移动,无需另外施加任何力或速度或改变 footBall 的 x 位置。 footBall 随行随行,效果很好。
起初,这个新方法并没有正常工作,我通过反复试验发现原因是"footBall.physicsBody?.allowsRotation = false"不能在footBall上指定为属性。但是,通过取消注释这一行它可以正常工作。
本练习的重点是使用 footBall 作为跳跃测试点,用于测试球员在跳跃过程中双脚何时伸展。所以 footBall 因此略微领先于主要球员的 body。然后我会根据跳跃的需要动态打开或关闭这个 footBall。
"foot sensor" 上的以下页面有些相关: http://gamedevwithoutacause.com/?p=1076 http://www.iforce2d.net/b2dtut/jumpability