使用固定的 SKPhysicsJoint 将平台检测碰撞框作为 child 附加到玩家精灵会更改玩家的碰撞和检测位掩码
Using a fixed SKPhysicsJoint to attach a platform detection hitbox as a child to a player sprite changes player's collision and detection bit masks
我正在尝试在我的播放器底部添加一个碰撞框以仅检测平台。经过大量的试验和错误后,我想出了一个额外的物理 body 作为 child 在固定位置附加到另一个物理 body 我需要使用 SKPhysicsJoint。我这样做了,它似乎有一个不可预见的后果。当我以这种方式将碰撞箱添加到玩家时,它会稍微改变玩家的碰撞/接触位掩码。
在我的游戏中,您点击屏幕即可跳跃,它可以无缝运行,没有延迟,如下所示:
但是当我用关节添加这个碰撞箱时,我必须用手指按住屏幕,最终玩家会跳起来,但大多数时候输入被忽略了。在阅读 input.In 这个 gif 时几乎好像有某种严重的滞后我不断地点击屏幕试图让我的玩家跳跃并且很多输入被忽略或阻止:
此函数在我的 gamescene.swift 中设置播放器,并通过固定的 SKPhysicsJoint 将碰撞框添加到播放器到场景:
func playerSetup(){
//setups player
addChild(player)
player.addChild(playerPlatformHitbox)
let myCGPoint = player.position // sets joint position
let myJoint = SKPhysicsJointFixed.joint(withBodyA: playerPlatformHitbox.physicsBody!, bodyB: player.physicsBody!, anchor: myCGPoint)
scene?.physicsWorld.add(myJoint)
}
这是我制作的命中框 class 只为玩家检测平台。你会看到它应该忽略所有期望来自位掩码的平台。出于某种原因,它不允许玩家接受与它的位掩码的接触,即使这个 hitbox 和玩家没有接触:
import Foundation
import SpriteKit
class PlayerPlatformHitbox: SKSpriteNode{
init() {
super.init(texture: nil, color: SKColor.blue, size: CGSize(width: playerTexture.size().width, height: 10))
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
position = CGPoint(x:0, y: (-playerTexture.size().height * 0.6))
physicsBody?.categoryBitMask = CollisionTypes.jumpHitBox.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.platform.rawValue
physicsBody?.collisionBitMask = CollisionTypes.platform.rawValue
physicsBody?.restitution = 0.0
physicsBody?.friction = 0.0
zPosition = 20
physicsBody?.linearDamping = 0.0
physicsBody?.angularDamping = 0.0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)}
}
这是我的播放器class
class Player: SKSpriteNode {
init() {
super.init(texture: nil, color: SKColor.clear, size: playerTexture.size())
//starts accelerameter
motionManager = CMMotionManager()
motionManager.startAccelerometerUpdates()
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: playerTexture.size().width,
height: playerTexture.size().height))
physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.memoryModule.rawValue | CollisionTypes.spikes.rawValue | CollisionTypes.finish.rawValue | CollisionTypes.enemy.rawValue | CollisionTypes.ground.rawValue
physicsBody?.collisionBitMask = CollisionTypes.ground.rawValue | CollisionTypes.sceneEdge.rawValue
physicsBody?.affectedByGravity = true
physicsBody?.restitution = 0.0
physicsBody?.friction = 0.3
physicsBody?.isDynamic = true
//physicsBody?.friction = 0.0
physicsBody?.allowsRotation = false
setScale(0.65)
zPosition = 1
physicsBody?.linearDamping = 0.0
physicsBody?.angularDamping = 0.0
animateWalk()
}
所有这一切的目标是在我的更新方法中使用 hitbox 来检测平台而不是玩家:
//jump through platform check
if let body = player.physicsBody {
let dy = body.velocity.dy
if dy > 0{
// Prevent collisions if the hero is jumping
body.collisionBitMask &= ~CollisionTypes.platform.rawValue
body.contactTestBitMask &= ~CollisionTypes.platform.rawValue
}
else {
// Allow collisions if the hero is falling
body.collisionBitMask |= CollisionTypes.platform.rawValue
body.contactTestBitMask |= CollisionTypes.platform.rawValue
}
}
我需要这样做的唯一原因是因为当玩家坠落时,如果他坠落并撞到平台的一侧,他将停下来并滑下平台,因为碰撞又回来了,玩家物理body 是一个正方形。
如果我可以使用平台检测 Hitbox 来检测平台而不是玩家笨重的 Hitbox 它将摆脱这个问题。
感谢所有建议。
编辑:这是 child 具有物理学 body 且没有关节的行为:
我找到了解决方案。
固定关节似乎存在一些错误,答案是改用 "pin" 关节。 This StackO question 详细介绍了固定关节的旋转错误。一时兴起,我决定将我的固定关节改为销钉,现在 child 的行为与您预期的一样,无论如何从位置上讲。
看来固定关节有一些问题需要解决。
我正在尝试在我的播放器底部添加一个碰撞框以仅检测平台。经过大量的试验和错误后,我想出了一个额外的物理 body 作为 child 在固定位置附加到另一个物理 body 我需要使用 SKPhysicsJoint。我这样做了,它似乎有一个不可预见的后果。当我以这种方式将碰撞箱添加到玩家时,它会稍微改变玩家的碰撞/接触位掩码。
在我的游戏中,您点击屏幕即可跳跃,它可以无缝运行,没有延迟,如下所示:
但是当我用关节添加这个碰撞箱时,我必须用手指按住屏幕,最终玩家会跳起来,但大多数时候输入被忽略了。在阅读 input.In 这个 gif 时几乎好像有某种严重的滞后我不断地点击屏幕试图让我的玩家跳跃并且很多输入被忽略或阻止:
此函数在我的 gamescene.swift 中设置播放器,并通过固定的 SKPhysicsJoint 将碰撞框添加到播放器到场景:
func playerSetup(){
//setups player
addChild(player)
player.addChild(playerPlatformHitbox)
let myCGPoint = player.position // sets joint position
let myJoint = SKPhysicsJointFixed.joint(withBodyA: playerPlatformHitbox.physicsBody!, bodyB: player.physicsBody!, anchor: myCGPoint)
scene?.physicsWorld.add(myJoint)
}
这是我制作的命中框 class 只为玩家检测平台。你会看到它应该忽略所有期望来自位掩码的平台。出于某种原因,它不允许玩家接受与它的位掩码的接触,即使这个 hitbox 和玩家没有接触:
import Foundation
import SpriteKit
class PlayerPlatformHitbox: SKSpriteNode{
init() {
super.init(texture: nil, color: SKColor.blue, size: CGSize(width: playerTexture.size().width, height: 10))
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
position = CGPoint(x:0, y: (-playerTexture.size().height * 0.6))
physicsBody?.categoryBitMask = CollisionTypes.jumpHitBox.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.platform.rawValue
physicsBody?.collisionBitMask = CollisionTypes.platform.rawValue
physicsBody?.restitution = 0.0
physicsBody?.friction = 0.0
zPosition = 20
physicsBody?.linearDamping = 0.0
physicsBody?.angularDamping = 0.0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)}
}
这是我的播放器class
class Player: SKSpriteNode {
init() {
super.init(texture: nil, color: SKColor.clear, size: playerTexture.size())
//starts accelerameter
motionManager = CMMotionManager()
motionManager.startAccelerometerUpdates()
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: playerTexture.size().width,
height: playerTexture.size().height))
physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.memoryModule.rawValue | CollisionTypes.spikes.rawValue | CollisionTypes.finish.rawValue | CollisionTypes.enemy.rawValue | CollisionTypes.ground.rawValue
physicsBody?.collisionBitMask = CollisionTypes.ground.rawValue | CollisionTypes.sceneEdge.rawValue
physicsBody?.affectedByGravity = true
physicsBody?.restitution = 0.0
physicsBody?.friction = 0.3
physicsBody?.isDynamic = true
//physicsBody?.friction = 0.0
physicsBody?.allowsRotation = false
setScale(0.65)
zPosition = 1
physicsBody?.linearDamping = 0.0
physicsBody?.angularDamping = 0.0
animateWalk()
}
所有这一切的目标是在我的更新方法中使用 hitbox 来检测平台而不是玩家:
//jump through platform check
if let body = player.physicsBody {
let dy = body.velocity.dy
if dy > 0{
// Prevent collisions if the hero is jumping
body.collisionBitMask &= ~CollisionTypes.platform.rawValue
body.contactTestBitMask &= ~CollisionTypes.platform.rawValue
}
else {
// Allow collisions if the hero is falling
body.collisionBitMask |= CollisionTypes.platform.rawValue
body.contactTestBitMask |= CollisionTypes.platform.rawValue
}
}
我需要这样做的唯一原因是因为当玩家坠落时,如果他坠落并撞到平台的一侧,他将停下来并滑下平台,因为碰撞又回来了,玩家物理body 是一个正方形。
如果我可以使用平台检测 Hitbox 来检测平台而不是玩家笨重的 Hitbox 它将摆脱这个问题。
感谢所有建议。
编辑:这是 child 具有物理学 body 且没有关节的行为:
我找到了解决方案。
固定关节似乎存在一些错误,答案是改用 "pin" 关节。 This StackO question 详细介绍了固定关节的旋转错误。一时兴起,我决定将我的固定关节改为销钉,现在 child 的行为与您预期的一样,无论如何从位置上讲。
看来固定关节有一些问题需要解决。