我正在尝试在我的一些精灵上实现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;
}
答案 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后缀的新文件夹,并将其放在应用程序包的Resource文件夹中。 这些新图像会自动旋转和修剪,以使最大数量的图像适合单个文件,其图像和方向由与文件夹关联的属性列表(.plist)跟踪。您无需更改代码即可使用纹理图集功能。
这是Apple使用的插图(注意轮换):