SpriteKit bodyWithTexture 未对齐
SpriteKit bodyWithTexture misaligned
我正在尝试在我的一些 sprite 上实现 bodyWithTexture,它在大多数情况下都很好用。我的问题是,出于某种原因,创建的物理体与我的精灵的实际形状不一致。我注意到它与纹理图集 Xcode 生成有关,它旋转有问题的精灵以适应。这是 issue.
的图像
我该如何解决这个问题?提前致谢!
注意:我试过这个 的内容,但没有成功。
注 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;
}
您遇到了 bodyWithTexture 方法的 sprite-kit 错误。
物理体实际上是颠倒的,没有错位或旋转。因此它与 .
完全相同
这是 iOS8 上 Spritekit 中的一个错误。我怀疑当物理体的纹理从内部缓存中检索时会出现错误。尝试从 CoreGraphics 校正坐标系可能会错误地翻转图像。
在你的情况下,考虑到你的小行星的形状,我推荐这个:
init!(polygonFromPath path: CGPath!) -> SKPhysicsBody
根据您发布的代码,您使用的是图像而不是精灵纹理。
至于旋转的精灵,SK 确实需要 space 优化来创建纹理图集。这包括图像旋转和修剪。我怀疑你在 SK 将旋转设置回它应该的位置之前添加了一个物理体。返回小行星后尝试添加物理体。
如果这不能解决您的问题,我建议您使用像 Texture Packer 这样的应用创建您自己的纹理图集。 Texture Packer 的功能之一是 allow/disallow 图像旋转。
苹果docs关于SK如何实现纹理图集的说法,供大家参考:
After the app is built, new folders are created with a .atlasc suffix and placed in your app bundle’s Resource folder. Those new images are automatically rotated and trimmed to fit the maximum number of images into a single file, one whose images and orientation are tracked by a property list (.plist) associated with the folder. You do not need to change your code in order to use the texture atlas feature.
这是Apple使用的插图(注意旋转):
我正在尝试在我的一些 sprite 上实现 bodyWithTexture,它在大多数情况下都很好用。我的问题是,出于某种原因,创建的物理体与我的精灵的实际形状不一致。我注意到它与纹理图集 Xcode 生成有关,它旋转有问题的精灵以适应。这是 issue.
的图像我该如何解决这个问题?提前致谢!
注意:我试过这个
更新:这是用于设置物理体的所有代码。至于纹理,我让 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;
}
您遇到了 bodyWithTexture 方法的 sprite-kit 错误。
物理体实际上是颠倒的,没有错位或旋转。因此它与
这是 iOS8 上 Spritekit 中的一个错误。我怀疑当物理体的纹理从内部缓存中检索时会出现错误。尝试从 CoreGraphics 校正坐标系可能会错误地翻转图像。
在你的情况下,考虑到你的小行星的形状,我推荐这个:
init!(polygonFromPath path: CGPath!) -> SKPhysicsBody
根据您发布的代码,您使用的是图像而不是精灵纹理。
至于旋转的精灵,SK 确实需要 space 优化来创建纹理图集。这包括图像旋转和修剪。我怀疑你在 SK 将旋转设置回它应该的位置之前添加了一个物理体。返回小行星后尝试添加物理体。
如果这不能解决您的问题,我建议您使用像 Texture Packer 这样的应用创建您自己的纹理图集。 Texture Packer 的功能之一是 allow/disallow 图像旋转。
苹果docs关于SK如何实现纹理图集的说法,供大家参考:
After the app is built, new folders are created with a .atlasc suffix and placed in your app bundle’s Resource folder. Those new images are automatically rotated and trimmed to fit the maximum number of images into a single file, one whose images and orientation are tracked by a property list (.plist) associated with the folder. You do not need to change your code in order to use the texture atlas feature.
这是Apple使用的插图(注意旋转):