Swift 3(SpriteKit):锁定SKSpriteNode及其physicsBody的x轴

6
我需要知道如何锁定SKSpriteNode及其物理体的x轴。我需要保持SKSpriteNode的dynamic和affectedByGravity状态。由于节点在斜坡上,所以它的x轴会因重力而移动。但是,我不希望这个SKSpriteNode的x轴因重力而移动。有没有一种方法可以锁定x轴以实现这一点? 谢谢任何帮助:D
编辑:我尝试将约束应用于x值,如下所示:
let xConstraint = SKConstraint.positionX(SKRange(constantValue: 195))
node.constraints?.append(xConstraint)

然而这并不起作用,我不确定如何解决。有人知道解决办法吗?

编辑2:SKPhysicsJointPin 看起来更有希望。在这个问题的第一个回答的评论中,我一直在试图弄清楚如何在我的情况下正确使用它。

我的代码示例:

let node = SKSpriteNode(imageNamed: "node")

enum collisionType: UInt32 {
    case node = 1
    case ground = 2
    case other = 4 //the other node is unrelated to the ground and node
}

class GameScene: SKScene, SKPhysicsContactDelegate {

override func didMove(to view: SKView) {
    //Setup node physicsBody
    node.physicsBody = SKPhysicsBody(rectangleOf: node.size)
    node.physicsBody?.categoryBitMask = collisionType.node.rawValue
    node.physicsBody?.collisionBitMask = //[other node that isn't the ground or the node]
    node.physicsBody?.contactTestBitMask = //[other node that isn't the ground or the node]
    node.physicsBody?.isDynamic = true
    node.physicsBody?.affectedByGravity = true
    addChild(node)

    //Physics Setup
    physicsWorld.contactDelegate = self
}

节点位于地面之上,而地面由各种具有基于体积的物理属性的SKSpriteNode线条组成。地面在前方不断添加新的线条,删除后方的线条,并将每个线条的x值更改为负数(这样地面似乎在移动-此过程在SKAction中执行)。这些线条(地面的部分)呈角度状,这就是为什么节点的x轴移动的原因。我希望节点始终位于地面的前端(例如,始终位于新创建的线条之上)。目前,像这样设置节点的位置会锁定x轴(解决了我的问题):
override func didSimulatePhysics() {
    //Manage node position
    node.position.x = 195
    node.position.y = CGFloat([yPosition of the first line of the ground - the yPosition keeps changing]) 
}

注意:^此^函数位于GameScene类中

实际上,x轴保持不变就像这样。然而,问题在于节点的物理体现在比节点的中心低(这在之前是不会发生的)。


你的意思是说你不希望x轴受到重力的影响而移动吗?重力不会影响精灵在x轴上的运动,也许你需要更好地解释问题。 - Knight0fDragon
@J.Treutlein 约束是实现你想要的方式。可以用于此的关节不是销轴,而是 SCNPhysicsSliderJoint,其中你可以欺骗第二个物体(没有质量、碰撞、接触等)。 - Confused
@J.Treutlein 我怀疑你的代码中可能还有其他不完整或不正确的地方,这可能会阻止约束提供你想要的效果,因为这确实应该是实现你目标的最好的“正确”方式。而且应该可以工作。你能否开始一个新项目,在苹果页面上使用位置约束示例,链接在这里:https://developer.apple.com/reference/spritekit/skconstraint(第一个),并使其按照你的意愿运行,只在y轴上影响你的对象?如果不能,那么SpriteKit可能存在错误。这不幸的情况并非第一次发生。 - Confused
认为他的重力已经改变并不荒谬,因为就像我说的,如果他确实改变了,他就知道他的问题出在哪里。这就是为什么我要求发帖者进一步解释他的问题,因为施加的力只是一个Y轴力。这意味着倾斜、旋转和滑动是由其他力造成的,而不是重力。因此,你解释“重力”是浪费时间。 - Knight0fDragon
@Confused 其实,我认为当我设置view.showPhysics = true时,physicsBody偏离中心只是一个视觉上的故障,因为如果physicsBody在中心,节点的物理效果正常。不过还是感谢您的建议。 - J.Treutlein
显示剩余10条评论
2个回答

5

默认情况下,节点的 constraints 属性为 nil。您需要创建一个包含一个或多个约束条件的数组,并将其分配给该属性。例如:

let xConstraint = SKConstraint.positionX(SKRange(constantValue: 195))
node.constraints = [xConstraint]

更新

您可能希望使用相机节点而不是在场景中移动地面。使用相机节点,您可以移动主角和相机,而不是地面。

enter image description here


由于某些原因,这并没有帮助,但还是谢谢。 - J.Treutlein
这应该与您添加到“didSimulatePhysics”的代码非常相似。当您将其添加到“didMove”方法中时会发生什么? - 0x141E
X轴位置仍在移动,没有受到限制。 - J.Treutlein
@J.Treutlein 请看关于相机的更新。这就是我在第三个评论中所说的关于使用相机的事情。它完全改变了你思考这个问题的方式,并为你在生成和越过地面时提供了一个自由的水平(请原谅双关语)。你可以像这个答案中所做的那样,也可以将相机下面的几何形状移动,或者混合两者。 - Confused
非常感谢。看起来很棒,尽管我已经通过使用其他人的评论解决了我的特定问题。虽然我肯定将来会用到这个,对于任何有同样问题的人来说,这是一个很好的解决方案。谢谢! - J.Treutlein

3

我认为你可以将linearDamping属性设置为0.0

linearDamping是一种减少物体线性速度的属性。

此属性用于模拟对物体施加的流体或空气摩擦力。属性必须是0.0到1.0之间的值。默认值为0.1。如果值为0.0,则不会对对象施加线性阻尼。

您还应该注意应用于SKSpriteNode的其他力。例如,物理世界施加的重力作用,其中dx值应设置为0.0:

CGVector(dx:0.0, dy:-4.9)

请记住,当您应用其他力量向量(如速度)时,如果要阻止x轴移动,请将dx属性保持为0.0。 您可以在官方文档中找到更多详细信息。
更新(根据您下面的评论):
您还可以使用SKPhysicsJoint将精灵锚定到地面(我不知道您的项目,所以这只是一个示例)。
var myJoint = SKPhysicsJointPin.joint(withBodyA: yourSprite.physicsBody!, bodyB: yourGround.physicsBody!, anchor: CGPoint(x: yourSprite.frame.minX, y: yourGround.frame.minY))

self.physicsWorld.add(myJoint)

你可以使用锚点属性来创建你想要的良好连接或添加更多的连接。

如果你有一个对角线直线,那么你的精灵也会受到垂直力的影响(例如重力..),不仅仅是水平方向上的。 - Alessandro Ornano
我明白这一点。但是,如果x轴被锁定并且永远不会改变,并且总是有一个表面在其下方,它将永远不会从屏幕上掉落。我可以接受y轴的更改,但是如果x轴被锁定并且永远不会改变,那么这些更改不应该影响x轴。 - J.Treutlein
请查看SKConstraint的positionX(_:) - 在https://developer.apple.com/reference/spritekit/skconstraint中讨论了“创建位置约束”。 - Flex Monkey
@J.Treutlein 是的,你可以更改 var enabled: Bool 属性。 - Alessandro Ornano
1
@J.Treutlein,你不应该在物理引擎中使用SKActions,否则会出现意外的结果。尝试查看并重写此method,并加入适当的条件(如果精灵存在,则执行...)。 - Alessandro Ornano
显示剩余18条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接