我使用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;
}
答案 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()
}
}
这是有效的,因为在为场景模拟物理场之前禁用了节点翻转。然后在渲染帧之前应用节点翻转。