SpriteKit SKPhysicsBody bodyWithTexture 颠倒了
SpriteKit SKPhysicsBody bodyWithTexture is Upside Down
您好,我正在尝试修复 spritekit 的物理形状倒置的错误。
[SKPhysicsBody bodyWithTexture:monsterTexture size:monsterTexture.size]
怪物第一次出现时物理body方向是正确的。但是第二次和之后每次出现怪物时,它的物理 body 都沿 Y 轴反转。请参见 skView.showsPhysics = true;
处的图片,以便显示物理形状。它第一次就可以正常工作的事实让我觉得可能有一些 属性 我不知道的东西正在被修改之类的。
我想将 2 个物理块放在靴子的粗略形状中,但这并不理想,因为我想使用其他一些更复杂的形状 bodyWithTexture,它们也遇到了同样的错误.
我也试过bodyWithTexture:monsterTexture
,原来的SKTextureobject而不是bodyWithTexture:monster.texture
,Monsterobject的贴图
这是我添加怪物的代码。如果您需要更多,请告诉我。
- (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;
}
我在 class 加载时缓存纹理
@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
似乎表现得更好,我正在考虑让所有怪物都成为圆形物理形状。
我认为这是 iOS8 上 Spritekit 中的一个错误。我怀疑当物理体的纹理从内部缓存中检索时会出现错误。尝试从 CoreGraphics 校正坐标系可能会错误地翻转图像。
改为使用 bodyWithBodies。真可惜,我真的很喜欢这个功能。
解决方案是对图集而不是纹理本身进行强引用。这也简化了我的代码,因为我已经在场景开始时用 [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]];
...
}
我能够通过在我的 didMoveToView 数组中根据我需要的可用纹理创建一个 SKPhysicsBody 数组来解决我的代码中的这个问题。当需要为我给定的 SKSpriteNode 更改时,我没有重新创建 SKPhysicsBody,而是能够在数组中引用已经创建的 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)。我假设旋转用于减小图集的整体图像大小。似乎由于纹理图集中的图像正在旋转,这在某种程度上影响了从纹理生成物理体的能力。
您好,我正在尝试修复 spritekit 的物理形状倒置的错误。
[SKPhysicsBody bodyWithTexture:monsterTexture size:monsterTexture.size]
怪物第一次出现时物理body方向是正确的。但是第二次和之后每次出现怪物时,它的物理 body 都沿 Y 轴反转。请参见 skView.showsPhysics = true;
处的图片,以便显示物理形状。它第一次就可以正常工作的事实让我觉得可能有一些 属性 我不知道的东西正在被修改之类的。
我想将 2 个物理块放在靴子的粗略形状中,但这并不理想,因为我想使用其他一些更复杂的形状 bodyWithTexture,它们也遇到了同样的错误.
我也试过bodyWithTexture:monsterTexture
,原来的SKTextureobject而不是bodyWithTexture:monster.texture
,Monsterobject的贴图
这是我添加怪物的代码。如果您需要更多,请告诉我。
- (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;
}
我在 class 加载时缓存纹理
@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
似乎表现得更好,我正在考虑让所有怪物都成为圆形物理形状。
我认为这是 iOS8 上 Spritekit 中的一个错误。我怀疑当物理体的纹理从内部缓存中检索时会出现错误。尝试从 CoreGraphics 校正坐标系可能会错误地翻转图像。
改为使用 bodyWithBodies。真可惜,我真的很喜欢这个功能。
解决方案是对图集而不是纹理本身进行强引用。这也简化了我的代码,因为我已经在场景开始时用 [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]];
...
}
我能够通过在我的 didMoveToView 数组中根据我需要的可用纹理创建一个 SKPhysicsBody 数组来解决我的代码中的这个问题。当需要为我给定的 SKSpriteNode 更改时,我没有重新创建 SKPhysicsBody,而是能够在数组中引用已经创建的 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)。我假设旋转用于减小图集的整体图像大小。似乎由于纹理图集中的图像正在旋转,这在某种程度上影响了从纹理生成物理体的能力。