SpriteKit – 制作一个不受重力影响的精灵(就像一个气球)
有没有人有任何想法,我可以让我的SKSpriteNode
反抗引力? 我想到了颠倒默认的重力,但意识到我也需要的东西掉下来!
这看起来应该很容易,但通过文档阅读我不明白我会怎么做!
谢谢
更新:在iOS 8 / OS X Yosemite(10.10)中,物理领域为这类问题提供了一个很好的解决scheme。 这里有一个快速的使用它们来为你的场景增加浮力(对于一组特定的节点)。
- 使用
linearGravityFieldWithVector
构造函数创build一个SKFieldNode
,提供与重力相反的vector,并将场节点添加到场景中。 - 将气球上的
fieldBitMask
设置为唯一的东西。 - 将字段上的
categoryBitMask
设置为与气球的fieldBitMask
重叠的fieldBitMask
,但不与任何其他主体的fieldBitMask
重叠。
现在,气球会上升或保持稳定,但其他物体会下降。 调整场地的strength
可以让你调整气球的浮力是否完美平衡重力(使它们漂浮在原地但受到干扰时),或稍微大于或小于重力(使其缓慢上升或下降)。
默认情况下,一个字段是无限的,覆盖整个场景,但是您可以使用字段的region
属性更改该字段,以将其限制为场景的一部分。 (如果要模拟水中的浮力,这是非常有用的 – 一旦物体从水面上升到水面上方,就会回落。)
此外,如果你想根据@ TheisEgeberg的答案想要浮力变化,你可以通过falloff
属性来控制它在距离上的变化。
在iOS 7 / OS X Mavericks(10.9)中,或者如果您想更精确地控制哪些力适用于何时何地,可以使用下面我原始答案中的方法。
如果你想要一个物体像一个气球一样漂浮 – 也就是浮力,受到重力的影响,但也会抵消它 – 你需要在每一帧(即在你的update:
方法)上施加一个力。
当心比例缩放:重力是一个恒定的加速度,但是如果你正在施加一个力来抵消重力,一个力与质量成正比。 要制作一个完美平衡重力的vector,以便在applyForce:
使用,您需要:
- 通过
{-1,-1,-1}
来缩放重力vector以指向相反的方向 - (
F = ma
,其中重力或反重力是a
)的大小。 - 规模
SKPhysicsWorld.gravity
150
– 有一个错误,其中SKPhysicsWorld.gravity
属性是不是在applyForce:
相同的单位。 (如果您closuresSKPhysicsWorld
重力并使用SKFieldNode
重力,则不需要这样做。)
与closuresaffectedByGravity
和应用动作来使气球上升不同,这种方法与物理模拟的其余部分很好的结合。 在平衡力与重力完全相等的情况下,气球就会漂浮在原地 – 与其他物体碰撞后,气球会恢复平衡。 如果平衡力大于重力,气球就会上升,但其上升会受到其他机构的阻碍。
首先, SKSpriteNode
根本不受重力的影响。 属于受重力影响的节点是SKPhysicsBody
。
第二…
myNode.physicsBody.afectedByGravity = NO;
:d
如果你想要它向上升起,那么你可以添加一个动作…
SKAction *moveAction = [SKAction moveByX:0 y:-10 duration:1]; SKAction *repeatingAction = [SKAction repeatActionForever:moveAction]; [myNode runAction:repeatingAction];
正如很多人所说的那样,这是关于反作用力的
所以是的,你可以对气球施加反作用力,使其向上。
但为了让它看起来像一个气球,你需要了解是什么使气球上升:气压。 由于您使用的氦气或其他轻气体比空气轻,因此会开始上升,换句话说,较重的空气会进入气球下方。 它就像一块木头在水中,更重的水将在木材下面,直到木材被浸泡,甚至比水更重。
所以你应该做的是使反作用力适应气球的高度,越高压力就越小。 这是一种模拟浮力的方法。
这是我的答案:
- (MyClass *)newRisingObject { MyClass *risingObject = [MyClass spriteNodeWithImageNamed:@"image"]; [risingObject setPosition:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame))]; [risingObject setName:@"name"]; [risingObject setUserInteractionEnabled:YES]; // Physics // [risingObject setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:risingObject.size.width / 2.0f]]; [risingObject.physicsBody setRestitution:1.0f]; [risingObject.physicsBody setFriction:0.0f]; [risingObject.physicsBody setLinearDamping:0.0f]; [risingObject.physicsBody setAngularDamping:0.0f]; [risingObject.physicsBody setMass:1.3e-6f]; return risingObject; }
。
- (void)didMoveToView:(SKView *)view { /* Setup your scene here */ MyClass *risingObject = [self newRisingObject]; [self addChild:risingObject]; }
。
- (void)update:(CFTimeInterval)currentTime { /* Called before each frame is rendered */ [self enumerateChildNodesWithName:@"name" usingBlock:^(SKNode *node, BOOL *stop) { // Push object up // [node.physicsBody applyImpulse:CGVectorMake(0.0f, node.physicsBody.mass * OBJECT_ACCELERATION)]; }]; }