SKPhysicsBody和[SKNode setScale:]

时间:2013-10-10 20:31:11

标签: ios7 sprite-kit

在我目前使用SpriteKit的项目中,我有一堆精灵需要在不同的时间独立地放大和缩小。问题是当我缩放节点时,物理体不会随之缩放,因此它会破坏物理学。这是我为了这个问题而放在一起的一个小例子:

CGSize objectSize = CGSizeMake(100, 100);
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];

SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize];
n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3);
n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize];
n1.physicsBody.affectedByGravity = YES;
[self addChild:n1];

SKSpriteNode *n2 = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:objectSize];
n2.position = CGPointMake(self.size.width/2, self.size.height/3);
n2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize];
n2.physicsBody.affectedByGravity = YES;
[self addChild:n2];

[n1 setScale:0.5];

enter image description here

注意蓝色精灵(按比例缩小)如何位于红色精灵之上,但你可以告诉它的物理体仍然具有我告诉它的尺寸,并且它没有缩放。

很明显,缩小节点不会缩小物理体。所以我的问题是如果我必须手动完成它,我该怎么做呢?

我尝试在缩放时用一个合适的尺寸交换身体,但如果旧的身体有关节等,事情会变得非常复杂......如果我能以某种方式缩放现有的身体,那就简单多了

6 个答案:

答案 0 :(得分:7)

使用SKAction或更新循环,您可以创建具有适当比例的新SKPhysicsBody并将其应用于对象。但是,通过这样做,您将失去速度。要解决此问题,您可以执行以下操作:

SKPhysicsBody *newBody = [SKPhysicsBody bodyWithRectangleOfSize:boxObject.size];
newBody.velocity = boxObject.physicsBody.velocity;

boxObject.physicsBody = newBody;

答案 1 :(得分:5)

物理身体形状无法缩放。绝对不是Box2D里面Sprite Kit内部使用的。

除了内部优化之外,扩展物理机构也会产生深远的影响。例如,缩放身体的形状可能会使身体陷入碰撞。它会影响关节的相互作用。它肯定会改变身体的密度或质量,从而改变它的行为。

您可以使用添加精灵的SKNode而不使用物理实体,然后使用给定大小的实体添加其他SKNode。然后,您可以在开始缩放精灵时启用或禁用实体。如果你正确计时,玩家将不会注意到碰撞形状只是从全尺寸变为半尺寸,而精灵会动画缩放过渡。

你必须根据它的大小计算身体的密度和其他属性。

答案 2 :(得分:3)

我遇到了完全相同的问题,我认为它是精灵套件中的一个错误。

尝试使用缩放操作,这适用于整个场景。

[self runAction:[SKAction scaleTo:0.5 duration:0]];

我原来的question

这是你想要发生的事吗

- (void) anthoertest
{
    CGSize objectSize = CGSizeMake(100, 100);
    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];

    SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize];
    n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3);
    n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n1.size];
    n1.physicsBody.affectedByGravity = YES;
    [self addChild:n1];

    SKSpriteNode *n2 = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:objectSize];
    n2.position = CGPointMake(self.size.width/2, self.size.height/3);
    n2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n2.size];
    n2.physicsBody.affectedByGravity = YES;
    [self addChild:n2];

    [self shrinkMe:n1];
}

- (void) shrinkMe:(SKSpriteNode *) s
{
    [s setScale:0.5];
    s.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:s.size];
}

enter image description here

答案 3 :(得分:3)

对于其他读这个答案的人,我相信现在物理学的身体与SKNode一起扩展。我正在使用Xcode 8.2.1和Swift 3.0.2。我开始一个新项目,选择游戏,填写详细信息。更改2个文件:

GameViewController.swift(添加一行)

view.showsFPS = true
view.showsNodeCount = true

// add this to turn on Physics Edges    
view.showsPhysics = true

Game Scene.swift(替换sceneDidLoad())函数:

override func sceneDidLoad() {

    var found = false
    self.enumerateChildNodes(withName: "testSprite") {
        node, stop in
            found = true
    }
    if !found {
        let testSprite = SKSpriteNode(color: UIColor.white, size: CGSize(width: 200.0, height: 200.0))
        testSprite.physicsBody = SKPhysicsBody(polygonFrom: CGPath(rect: CGRect(x: -100.0, y: -100.0, width: 200.0, height: 200.0), transform: nil))
        testSprite.physicsBody?.affectedByGravity = false
        testSprite.name = "testSprite"
        let scaleAction = SKAction.repeatForever(SKAction.sequence([
            SKAction.scale(to: 2.0, duration: 2.0),
            SKAction.scale(to: 0.5, duration: 2.0)
            ]))
        testSprite.run(scaleAction)
        self.addChild(testSprite)
    }

}

物理边界正在使用精灵节点进行缩放。

答案 4 :(得分:1)

物理体依赖于SKNode的CGPath;你需要以某种方式改变它。您可以尝试使用以下内容扩展CGPath:

//scale up

CGFloat scaleFactor = 1.1;
CGAffineTransform scaleTransform = CGAffineTransformIdentity;
scaleTransform = CGAffineTransformScale(scaleTransform, scaleFactor, scaleFactor);
CGPathRef scaledPathRef = CGPathCreateCopyByTransformingPath(exampleNode.path, &scaleTransform);
exampleNode.path = scaledPathRef;

但请记住,这不会更新已存在于SKScene中的节点的外观。您可能需要将CGPath的大小调整与扩展节点的SKAction结合使用。

答案 5 :(得分:0)

我有同样的问题,我所做的只是在我的更新当前时间函数中定义我的物理体,它会随之扩展。

对你而言,它会是这样的:

override func sceneDidLoad() {

SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize];
n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3);

}
override func update(_ currentTime: TimeInterval) {

n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize];
n1.physicsBody.affectedByGravity = YES;

}

唯一的问题是你必须每次在updateCurrentTime中重新定义你的物理属性。您可以将其中某些属性(例如它的恢复原理)等同于变量,以便您可以通过在其他位置更改变量来更改其属性。在其他任何地方重新定义它只会在下一帧被调用之前有效。