SpriteKit SKPhysics Тело тела с текстурой вверх ногами

Привет, я пытаюсь исправить эту ошибку, когда физическая форма спрайтекита появляется вверх ногами.

[SKPhysicsBody bodyWithTexture:monsterTexture size:monsterTexture.size]

В первый раз, когда появляется монстр, правильная ориентация физического тела. Но во второй раз и каждый раз после этого появляется монстр, его физическое тело переворачивается вдоль оси Y. Смотрите картинку где skView.showsPhysics = true; поэтому физические формы отображаются. Тот факт, что он работает правильно в первый раз, заставляет меня думать, что какое-то свойство, о котором я не знаю, изменяется или что-то в этом роде.

Я подумал о том, чтобы соединить 2 физических блока вместе в грубой форме загрузки, но это не идеально, так как есть некоторые другие более сложные формы, которые я хочу использовать для bodyWithTexture, которые испытывают ту же ошибку.

Я также пытался bodyWithTexture:monsterTextureисходный объект SKTexture вместо bodyWithTexture:monster.texture, текстура объекта Monster.

физика тело вверх ногами

Вот мой код добавления монстра. Дайте мне знать, если вам нужно больше.

- (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 ответа

Решение

Решение состояло в том, чтобы держать сильную ссылку на атлас вместо самих текстур. Это также упростило мой код, так как я уже загружаю все свои атласы [SKTextureAtlas preloadTextureAtlases:textureAtlases withCompletionHandler:^{ ... }]; в начале моей сцены. Кажется, что он использует тот же объем памяти (если не меньше), и больше не вызывает перевернутую физическую ошибку тела. Комментарии к этому вопросу ( следует ли мне кэшировать текстуры в свойствах набора спрайтов?) Помогли мне обнаружить это во время рефакторинга кода.

 // 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]];

      ...
 }

Я думаю, что это ошибка в Spritekit на iOS8. Я подозреваю, что ошибка возникает, когда текстура для физического тела извлекается из внутреннего кэша. Возможно, это неправильно перевернуло изображение, чтобы попытаться исправить системы координат из CoreGraphics.

Вместо этого используйте bodyWithBodies. Облом, мне очень нравится эта функция.

Я смог решить эту проблему в своем коде, создав массив SKPhysicsBody в моем массиве didMoveToView из доступных мне текстур. Вместо того, чтобы воссоздать 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-е физические тела будут работать, но остальные не появятся. Я смог извлечь текстурный список из устройства и обнаружил, что текстуры с 1 по 5 были повернуты (то есть textureRotated = YES в листе). Я предполагаю, что вращение используется для уменьшения общего размера изображения для атласа. Похоже, что поскольку изображения в текстурном атласе вращаются, это как-то влияет на способность генерировать физическое тело из текстуры.

Другие вопросы по тегам