SpriteKit bodyWithTexture未对齐

时间:2015-04-24 03:50:58

标签: ios objective-c sprite-kit

我正在尝试在我的一些精灵上实现bodyWithTexture,它在大多数情况下都很有用。我的问题是,由于某种原因,创建的物理实体不会与我的精灵的实际形状对齐。我注意到它与Xcode生成的纹理图集有关,它会旋转所讨论的精灵以适应。这是issue.

的图像

我该如何解决这个问题?提前谢谢!

注意:我已经尝试了这个post的内容而没有运气。 注2:我会在Objective-C中使用任何代码示例。

更新:以下是用于设置物理主体的所有代码。至于纹理我让SpriteKit在幕后处理。

@implementation AsteroidNode

+(instancetype)astroidOfType:(AstoridType)type {

      AsteroidNode *astroid;

    if (type == AstoridTypeA) {
        astroid = [self spriteNodeWithImageNamed:@"rock_a"];
        astroid.type = AstoridTypeA;
    } else if (type == AstoridTypeB) {
        astroid = [self spriteNodeWithImageNamed:@"rock_b"];
        astroid.type = AstoridTypeB;
    } else {
        astroid = [self spriteNodeWithImageNamed:@"rock_c"];
        astroid.type = AstoridTypeC;
    }

    astroid.name = @"astroid";
    astroid.zPosition = 1;

    //changes asteroid size for smaller screen sizes
    if ( IS_IPHONE_4_OR_LESS | IS_IPHONE_5) {
        astroid.size = [Utils setNodeSize:astroid.size];
    }
    [astroid setUpPhysicsBody];

    return astroid;
}

-(void)setUpPhysicsBody {   
    self.physicsBody = [SKPhysicsBody bodyWithTexture:self.texture size:self.size];
    self.physicsBody.friction = 0;
    self.physicsBody.linearDamping = 0;
    self.physicsBody.categoryBitMask = CollisionCatAstroid;
    self.physicsBody.collisionBitMask = 0;
    self.physicsBody.contactTestBitMask = CollisionCatShip | CollisionCatBottomEdge;
}
@end

使用bodyWithPolygonFromPath在6和6+上运行效果很好,但在5和4S上运行效果不佳。

CGFloat offsetX = self.size.width / 2;
CGFloat offsetY = self.size.height / 2;

if (self.type == AstoridTypeA) {
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathMoveToPoint(path, NULL, 20 - offsetX, 87 - offsetY);
    CGPathAddLineToPoint(path, NULL, 77 - offsetX, 86 - offsetY);
    CGPathAddLineToPoint(path, NULL, 103 - offsetX, 48 - offsetY);
    CGPathAddLineToPoint(path, NULL, 88 - offsetX, 13 - offsetY);
    CGPathAddLineToPoint(path, NULL, 63 - offsetX, 16 - offsetY);
    CGPathAddLineToPoint(path, NULL, 33 - offsetX, 5 - offsetY);
    CGPathAddLineToPoint(path, NULL, 3 - offsetX, 36 - offsetY);

    CGPathCloseSubpath(path);

    self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
} else if (self.type == AstoridTypeB) {
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathMoveToPoint(path, NULL, 43 - offsetX, 91 - offsetY);
    CGPathAddLineToPoint(path, NULL, 81 - offsetX, 80 - offsetY);
    CGPathAddLineToPoint(path, NULL, 97 - offsetX, 50 - offsetY);
    CGPathAddLineToPoint(path, NULL, 75 - offsetX, 10 - offsetY);
    CGPathAddLineToPoint(path, NULL, 25 - offsetX, 18 - offsetY);
    CGPathAddLineToPoint(path, NULL, 12 - offsetX, 36 - offsetY);
    CGPathAddLineToPoint(path, NULL, 10 - offsetX, 71 - offsetY);

    CGPathCloseSubpath(path);

    self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
} else {
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathMoveToPoint(path, NULL, 41 - offsetX, 48 - offsetY);
    CGPathAddLineToPoint(path, NULL, 55 - offsetX, 32 - offsetY);
    CGPathAddLineToPoint(path, NULL, 40 - offsetX, 10 - offsetY);
    CGPathAddLineToPoint(path, NULL, 24 - offsetX, 12 - offsetY);
    CGPathAddLineToPoint(path, NULL, 11 - offsetX, 23 - offsetY);
    CGPathAddLineToPoint(path, NULL, 17 - offsetX, 43 - offsetY);

    CGPathCloseSubpath(path);
    self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
}

我最终得到了这个,可能是一种更简单的方法,但它有效。如果有人有任何建议,请告诉我。

   -(void)setUpPhysicsBody {
        CGFloat offsetX = self.size.width / 2;
        CGFloat offsetY = self.size.height / 2;

        if (self.type == AstoridTypeA) {
            if (IS_IPHONE_4_OR_LESS | IS_IPHONE_5) {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 17 - offsetX, 72 - offsetY);
                CGPathAddLineToPoint(path, NULL, 64 - offsetX, 71 - offsetY);
                CGPathAddLineToPoint(path, NULL, 85 - offsetX, 40 - offsetY);
                CGPathAddLineToPoint(path, NULL, 73 - offsetX, 10 - offsetY);
                CGPathAddLineToPoint(path, NULL, 52 - offsetX, 13 - offsetY);
                CGPathAddLineToPoint(path, NULL, 27 - offsetX, 4 - offsetY);
                CGPathAddLineToPoint(path, NULL, 2 - offsetX, 30 - offsetY);

                CGPathCloseSubpath(path);

                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
            } else {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 20 - offsetX, 87 - offsetY);
                CGPathAddLineToPoint(path, NULL, 77 - offsetX, 86 - offsetY);
                CGPathAddLineToPoint(path, NULL, 103 - offsetX, 48 - offsetY);
                CGPathAddLineToPoint(path, NULL, 88 - offsetX, 13 - offsetY);
                CGPathAddLineToPoint(path, NULL, 63 - offsetX, 16 - offsetY);
                CGPathAddLineToPoint(path, NULL, 33 - offsetX, 5 - offsetY);
                CGPathAddLineToPoint(path, NULL, 3 - offsetX, 36 - offsetY);

                CGPathCloseSubpath(path);

                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
            }
          } else if (self.type == AstoridTypeB) {
            if (IS_IPHONE_4_OR_LESS | IS_IPHONE_5) {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 35 - offsetX, 75 - offsetY);
                CGPathAddLineToPoint(path, NULL, 67 - offsetX, 66 - offsetY);
                CGPathAddLineToPoint(path, NULL, 80 - offsetX, 41 - offsetY);
                CGPathAddLineToPoint(path, NULL, 62 - offsetX, 8 - offsetY);
                CGPathAddLineToPoint(path, NULL, 20 - offsetX, 15 - offsetY);
                CGPathAddLineToPoint(path, NULL, 10 - offsetX, 30 - offsetY);
                CGPathAddLineToPoint(path, NULL, 8 - offsetX, 59 - offsetY);

                CGPathCloseSubpath(path);
                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
            } else {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 43 - offsetX, 91 - offsetY);
                CGPathAddLineToPoint(path, NULL, 81 - offsetX, 80 - offsetY);
                CGPathAddLineToPoint(path, NULL, 97 - offsetX, 50 - offsetY);
                CGPathAddLineToPoint(path, NULL, 75 - offsetX, 10 - offsetY);
                CGPathAddLineToPoint(path, NULL, 25 - offsetX, 18 - offsetY);
                CGPathAddLineToPoint(path, NULL, 12 - offsetX, 36 - offsetY);
                CGPathAddLineToPoint(path, NULL, 10 - offsetX, 71 - offsetY);

                CGPathCloseSubpath(path);

                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
            }
        } else {

            if (IS_IPHONE_4_OR_LESS | IS_IPHONE_5) {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 34 - offsetX, 40 - offsetY);
                CGPathAddLineToPoint(path, NULL, 45 - offsetX, 26 - offsetY);
                CGPathAddLineToPoint(path, NULL, 33 - offsetX, 8 - offsetY);
                CGPathAddLineToPoint(path, NULL, 20 - offsetX, 10 - offsetY);
                CGPathAddLineToPoint(path, NULL, 9 - offsetX, 19 - offsetY);
                CGPathAddLineToPoint(path, NULL, 14 - offsetX, 35 - offsetY);

                CGPathCloseSubpath(path);

                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path]; 
            } else {
                CGMutablePathRef path = CGPathCreateMutable();

                CGPathMoveToPoint(path, NULL, 41 - offsetX, 48 - offsetY);
                CGPathAddLineToPoint(path, NULL, 55 - offsetX, 32 - offsetY);
                CGPathAddLineToPoint(path, NULL, 40 - offsetX, 10 - offsetY);
                CGPathAddLineToPoint(path, NULL, 24 - offsetX, 12 - offsetY);
                CGPathAddLineToPoint(path, NULL, 11 - offsetX, 23 - offsetY);
                CGPathAddLineToPoint(path, NULL, 17 - offsetX, 43 - offsetY);

                CGPathCloseSubpath(path);

                self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
            }
        }

        self.physicsBody.friction = 0;
        self.physicsBody.linearDamping = 0;
        self.physicsBody.categoryBitMask = CollisionCatAstroid;
        self.physicsBody.collisionBitMask = 0;
        self.physicsBody.contactTestBitMask = CollisionCatShip | CollisionCatBottomEdge;
    }

2 个答案:

答案 0 :(得分:1)

您遇到了使用bodyWithTexture方法的sprite-kit错误。

物理实体实际上是倒置的,没有错位或旋转。因此它与this issue完全相同。

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

根据你的小行星的形状,我推荐这个:

init!(polygonFromPath path: CGPath!) -> SKPhysicsBody

答案 1 :(得分:1)

根据您发布的代码,您使用的是图片,而不是精灵的纹理。

对于旋转的精灵,SK确实优化了创建纹理图集所需的空间。这包括图像旋转和修剪。我怀疑你在SK将旋转设置回应该是什么之前添加一个物理体。返回小行星后尝试添加物理实体。

如果这不能解决您的问题,我建议您使用Texture Packer这样的应用创建自己的纹理图集。 Texture Packer的一个功能是允许/禁止图像旋转。

供大家参考,这就是Apple docs关于SK如何实现纹理地图集的说法:

  

构建应用程序后,将创建一个带有.atlasc后缀的新文件夹,并将其放在应用程序包的Res​​ource文件夹中。 这些新图像会自动旋转和修剪,以使最大数量的图像适合单个文件,其图像和方向由与文件夹关联的属性列表(.plist)跟踪。您无需更改代码即可使用纹理图集功能。

这是Apple使用的插图(注意轮换):

enter image description here