翻转的x-scale中断碰撞处理(SpriteKit 7.1)

时间:2014-03-17 12:25:45

标签: sprite-kit ios7.1 skphysicsbody xscale

我使用SKNode的xScale属性水平翻转我的精灵。现在,在将iOS更新到版本7.1之后,水平翻转会导致我的对象沉入地下。 (见下面的动画)。只有xScale属性才会出现此问题。垂直翻转工作正常。

// Init
{
    SKSpriteNode* ground = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:CGSizeMake(winSize.width, 150)];
    ground.position = CGPointMake(winSize.width/2, ground.size.height/2);
    ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size center:CGPointZero];
    ground.physicsBody.dynamic = NO;
    ground.physicsBody.categoryBitMask = 0x01;
    ground.physicsBody.collisionBitMask = 0x02;
    ground.physicsBody.contactTestBitMask = 0x02;
    [self.world addChild:ground];

    SKSpriteNode* turtle = [SKSpriteNode spriteNodeWithImageNamed:@"turtle.png"];
    turtle.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:turtle.size.width/2];
    turtle.physicsBody.categoryBitMask = 0x02;
    turtle.physicsBody.collisionBitMask = 0x01;
    turtle.physicsBody.contactTestBitMask = 0x01;
    turtle.position = CGPointMake(winSize.width/2, winSize.height/2);
    [self.world addChild:turtle];
    self.turtle = turtle;
}

// Somewhere else
{
    self.turtle.xScale *= -1;
}

x-scale flip problem

3 个答案:

答案 0 :(得分:12)

我确信这是SpriteKit中的一个错误。

无论如何,这里有一个问题的解决方案(实际上,这是一个解决方法而不是真正的解决方案,但是......):将精灵包装在容器节点中。此外,容器节点保持不变physicsBody,而子节点只是一个图形节点。这样,您可以使用xScale安全地翻转精灵,而不会影响节点的物理特性。

// Init
{
    SKSpriteNode* turtleSprite = [SKSpriteNode spriteNodeWithImageNamed:@"turtle.png"];
    self.turtleSprite = turtleSprite;

    SKNode* turtleWrapper = [SKNode node]; 
    turtleWrapper.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:turtleSprite.size.width/2];
    turtleWrapper.physicsBody.categoryBitMask = 2;
    turtleWrapper.physicsBody.collisionBitMask = 1;
    turtleWrapper.physicsBody.contactTestBitMask = 1;

    [turtleWrapper addChild:turtleSprite];
    [self.world addChild:turtleWrapper];
}

// Elsewhere
{
    self.turtleSprite.xScale *= -1;
}

答案 1 :(得分:6)

我几天前遇到过这个问题。我想根据它的移动(向右或向左)反转精灵,并发现设置xScale会禁用任何碰撞/接触。

但是,每次设置xScale属性时都会使用此行,一切都恢复正常。

node.xScale = -1.0
node.physicsBody = node.physicsBody;

答案 2 :(得分:0)

替代解决方案

在我的情况下,我通常子类SKSpriteNode 来表示我的场景中的节点,然后将它们的行为(动画和移动)封装在子类中。容器节点解决方案中的 Wrap sprite在我的情况下不起作用,因为我有动作为sprite纹理设置动画并且还按顺序移动sprite。

例如:

class Player: SKSpriteNode{

    override init() {
        ...
        super.init(texture: texture, color: nil, size: texture.size())
        physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70,75))
    }

    func attack(){
        let action = SKAction.sequence([
            SKAction.moveTo(enemyPosition, duration: 0),
            SKAction.animateWithTextures(frames, timePerFrame: 0.5)
            ])
        runAction(action)
    }
}

解决方法

在我的情况下,我通过将这些方法添加到我的播放器'类:

class Player: SKSpriteNode{
    private var flipped: Bool
    ...

    func flip(){
        flipped = !flipped
        position = CGPointMake(-position.x, position.y)
    }

    //MARK: Workaround for iOS7 -xScale physics bugs
    func willSimulatePhysics(){
        xScale = 1
    }

    func didSimulatePhysics(){
        xScale = flipped ? -1 : 1
    }
}

然后覆盖SKScene方法:

class MyScene: SKScene{
    ...

    override func update(currentTime: CFTimeInterval) {
        super.update(currentTime)
        player.willSimulatePhysics()
    }

    override func didSimulatePhysics() {
        super.didSimulatePhysics()
        player.didSimulatePhysics()
    }
}

这是有效的,因为在为场景模拟物理场之前禁用了节点翻转。然后在渲染帧之前应用节点翻转。