SpriteKit SKPhysicsBody bodyWithTexture颠倒了

时间:2015-01-02 20:17:34

标签: ios objective-c sprite-kit game-physics skphysicsbody

您好,我试图修复这个错误,spritekit的物理形状出现颠倒。

[SKPhysicsBody bodyWithTexture:monsterTexture size:monsterTexture.size]

怪物第一次出现时,身体的方向是正确的。但是第二次以及每次在怪物出现之后,它的物理体都沿着Y轴反转。请参见图片skView.showsPhysics = true;,以便显示物理形状。它第一次正常工作这一事实让我觉得可能有一些我不知道的属性正在被修改或其他什么。

我想过将2个物理块放在靴子的粗糙形状中,但这并不理想,因为还有一些其他更复杂的形状,我想使用bodyWithTexture来体验相同的bug。

我还尝试了bodyWithTexture:monsterTexture,原始的SKTexture对象,而不是bodyWithTexture:monster.texture,即Monster对象的纹理。

physics body upside down

这是我的添加怪物代码。如果您需要更多,请告诉我。

- (Monster *)monster:(NSDictionary *)settings
{
    NSDictionary * monsterDefaults = [self monsterDefaults];
    NSDictionary * monsterConfig   = [self monsterConfig:settings[TYPE]];
    SKTexture * monsterTexture     = monsterConfig[TEXTURE] ? monsterConfig[TEXTURE] : monsterDefaults[TEXTURE];
    Monster * monster              = [Monster spriteNodeWithTexture:monsterTexture];

    // Animation
    if (monsterConfig[ANIMATION]) {
        [monster runAction:monsterConfig[ANIMATION]];
    }

    // Moster Stats
    monster.name   = MONSTER_SPRITE;
    monster.type   = settings[TYPE];
    monster.points = monsterConfig[POINTS] ? [monsterConfig[POINTS] intValue] : [monsterDefaults[POINTS] intValue];
    monster.damage = monsterConfig[DAMAGE] ? [monsterConfig[DAMAGE] intValue] : [monsterDefaults[DAMAGE] intValue];
    monster.hp     = monsterConfig[HP]     ? [monsterConfig[HP] intValue] : [monsterDefaults[HP] intValue];
    monster.lethal = monsterConfig[LETHAL] ? [monsterConfig[LETHAL] boolValue] : [monsterDefaults[LETHAL] boolValue];

    // Monster Physics
    float physicsResize = monsterConfig[RESIZE] ? [monsterConfig[RESIZE] floatValue] : [monsterDefaults[RESIZE] floatValue];
    switch ([monsterConfig[SHAPE] intValue]) {
        case COMPLEX:
            NSLog(@"%@", monster.texture);
            NSLog(@"rotation: %f", monster.zRotation);
            NSLog(@"x scale: %f", monster.xScale);
            NSLog(@"y scale: %f", monster.yScale);
            monster.physicsBody = [SKPhysicsBody bodyWithTexture:monster.texture size:monster.texture.size];
            break;
        case RECTANGLE:
            monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(monster.size.width * physicsResize, monster.size.height * physicsResize)];
            break;
        default:
            monster.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:(monster.size.height * physicsResize) / 2];
            break;
    }

    monster.physicsBody.dynamic             = false;
    monster.physicsBody.affectedByGravity   = false;
    monster.physicsBody.categoryBitMask     = monsterCategory;
    monster.physicsBody.contactTestBitMask  = weaponCategory | heroCategory;
    monster.physicsBody.collisionBitMask    = defaultCategory;

    // Monster Flight Pattern
    SKAction * flightPattern = [self monsterFlightPattern:monster settings:settings];

    // Monster Rotation
    // Rotation disabled for physics text
    // [self monsterRotation:monster rotationConfig:monsterConfig[ROTATION]];

    // Move & Remove
    SKAction * remove = [Config removeAction:monster];
    [monster runAction:[SKAction sequence:@[flightPattern, remove]]];

    return monster;
}

当我加载

时,我正在缓存纹理
@property (nonatomic) SKTexture * monsterBootTexture;
...

- (id)initWithFrameSize:(CGSize)frameSize
{
    ...
    SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:monsterAtlas];
    self.monsterBootTexture = [atlas textureNamed:MONSTER_BOOT];
    ...
}

NSLog的内容如下:

2015-01-02 12:03:20.619 Gadget Blaster[3301:665394] <SKTexture> 'boot.png' (97 x 100)
2015-01-02 12:03:20.623 Gadget Blaster[3301:665394] <SKTexture> 'boot.png' (97 x 100)

我已根据LearnCocos2D评论添加了以下日志:

2015-01-03 12:00:06.131 Gadget Blaster[3987:772046] rotation: 0.000000
2015-01-03 12:00:06.133 Gadget Blaster[3987:772046] x scale: 1.000000
2015-01-03 12:00:06.134 Gadget Blaster[3987:772046] y scale: 1.000000
2015-01-03 12:00:08.131 Gadget Blaster[3987:772046] rotation: 0.000000
2015-01-03 12:00:08.131 Gadget Blaster[3987:772046] x scale: 1.000000
2015-01-03 12:00:08.132 Gadget Blaster[3987:772046] y scale: 1.000000
2015-01-03 12:00:10.156 Gadget Blaster[3987:772046] rotation: 0.000000
2015-01-03 12:00:10.156 Gadget Blaster[3987:772046] x scale: 1.000000
2015-01-03 12:00:10.159 Gadget Blaster[3987:772046] y scale: 1.000000

此外,在使用复杂的物理实体时,我遇到了一些意外的碰撞问题。 SKPhysicsBody bodyWithCircleOfRadius似乎表现得更好,我考虑让所有怪物圈出物理形状。

3 个答案:

答案 0 :(得分:1)

我认为这是iOS8上Spritekit中的一个错误。我怀疑当从内部缓存中检索物理体的纹理时会发生错误。它可能会错误地翻转图像以尝试纠正CoreGraphics中的坐标系统。

改用bodyWithBodies。糟糕,我真的很喜欢这个功能。

答案 1 :(得分:0)

解决方案是强烈引用地图集而不是纹理本身。这也简化了我的代码正弦我已经在我的场景开始时用[SKTextureAtlas preloadTextureAtlases:textureAtlases withCompletionHandler:^{ ... }];预加载了我的所有地图集。这似乎使用相同数量的内存(如果不是更少),它不再产生颠倒的物理主体错误。关于这个问题的评论(should I cache textures in properties in sprite kit?)帮助我发现了这一点,因为我正在重构我的代码。

 // In Game Scene

 @property (nonatomic, strong) SKTextureAtlas * monsterAtlas;

 ...

 - (id)initWithSize:(CGSize)size
 {
      self.monsterAtlas = [SKTextureAtlas atlasNamed:monsterAtlasName];
      NSArray * textureAtlases = @[self.monsterAtlas];
      [SKTextureAtlas preloadTextureAtlases:textureAtlases withCompletionHandler:^{ ... }];
 }

 // In Monster Class

 - (Monster *)monster:(NSDictionary *)settings
 {
      ...

      SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:monsterAtlasName];
      NSString * textureName = monsterConfig[TEXTURE] ? monsterConfig[TEXTURE] : monsterDefaults[TEXTURE];
      Monster * monster      = [Monster spriteNodeWithTexture:[atlas textureNamed:textureName]];

      ...
 }

答案 2 :(得分:0)

我能够通过在我的didMoveToView数组中根据我需要的可用纹理创建一个SKPhysicsBody数组来解决我的代码中的这个问题。我可以在数组中引用已创建的SKPhysicsBody,而不是在需要为我的给定SKSpriteNode更改时重新创建SKPhysicsBody。这样可以防止纹理颠倒翻转。希望这种方法可以帮助其他人坚持这一点。

// variable declared in SKScene
var myPhysicsBodies: [SKPhysicsBody]()

// put in didMoveToView
for var i = 0; i <= 6; i++ {        
    self.myPhysicsBodies.append(SKPhysicsBody(texture: self.myTextureFrames[i], size: self.myObject.size))
}

// used when changing physicsBody
self.myObject.physicsBody = self.myPhysicsBodies[self.frameIndex]

更新: 在iOS 9 SDK之前,这一切都运行良好。我发现我的第0和第6个物理机构可以工作,但其他人不会出现。我能够从设备中提取texture.plist并发现纹理1到5被旋转(即,plist中的textureRotated = YES)。我假设旋转用于减少地图集的整体图像大小。看来,由于纹理图集中的图像正在旋转,这会以某种方式影响从纹理生成物理体的能力。