我创建了SKShapeNode
,并为其分配了physicsBody
。但是,当有联系时它不会被触发。
创建SKShapeNode
代码:
-(SKShapeNode*)gravityline{
//SKSpriteNode *lolo=[[SKSpriteNode alloc]init];
SKShapeNode *lolo = [[SKShapeNode alloc] init];
CGPoint fff=CGPointMake(ray1.position.x, ray1.position.y);
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, fff.x, fff.y);
CGPathAddLineToPoint(path, 0,rayoriginpoint.x,rayoriginpoint.y );
CGPathCloseSubpath(path);
lolo.path = path;
lolo.name=@"gravityline";
lolo.strokeColor=[SKColor greenColor];
lolo.glowWidth=.1;
CGPathRelease(path);
lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];
//lolo.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromPath:path];
//lolo.physicsBody=[SKPhysicsBody bodyWithPolygonFromPath:path];
lolo.physicsBody.categoryBitMask=raylightCategory;
lolo.physicsBody.collisionBitMask=batCategory;
lolo.physicsBody.contactTestBitMask=batCategory;
lolo.physicsBody.usesPreciseCollisionDetection=YES;
lolo.physicsBody.linearDamping=0;
lolo.physicsBody.restitution=1.0;
lolo.physicsBody.dynamic=NO;
return lolo;
}
以下是琐事代码:
- (void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask == raylightCategory && secondBody.categoryBitMask==batCategory)
{
NSLog(@"Contact with bat have been made");
[secondBody.node removeFromParent];
}
}
如果有人知道我做错了什么,为什么SKShapeNode
没有激活physicsBody,请告诉我。
答案 0 :(得分:0)
这当然行不通:
lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];
如果有的话,这将返回已分配给不同节点的主体。但我猜它只会返回nil。
此注释行也不起作用:
//lolo.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromPath:path];
边缘形状将创建静态(如:不可移动的)主体。因此,这个节点不会通过物理学进行移动,如果我没有弄错的话,你也不会得到静态物体的接触者的接触反应,只有动态物体。
这个应该有效:
//lolo.physicsBody=[SKPhysicsBody bodyWithPolygonFromPath:path];
但是你在这里将身体设置为静态身体:
lolo.physicsBody.dynamic=NO;
因此,相同的规则适用于您创建具有边循环的主体。
答案 1 :(得分:0)
您的代码并未完全显示您的“gravityLine”与之相撞的内容。我只能从它的描述中推测它没有检测到与圆形物体(球和蝙蝠)的碰撞。
“gravityLine”方法似乎返回一个由基于边缘的形状定义的SKShapeNode:
lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];
当涉及到碰撞时,重要的是阅读Apple的Sprite Kit编程指南,特别是它对三种形状的解释。
1)动态体积模拟物理对象的体积和质量,可能会受到系统中的力和碰撞的影响。使用动态卷来表示场景中需要移动并相互碰撞的项目。
2)静态体积类似于动态体积,但其速度被忽略,并且不受力或碰撞的影响。但是,因为它仍然具有音量,所以其他对象可以从其反弹或与之交互。使用静态卷表示占用场景空间的项目,但不应由模拟移动。例如,您可以使用静态卷来表示迷宫的墙壁。 虽然将静态和动态卷视为不同的实体很有用,但实际上这些是可以应用于任何基于体积的物理主体的两种不同模式。这可能很有用,因为您可以有选择地启用或禁用正文的效果。
3)边缘是静态无体积体。边缘永远不会被模拟移动,它们的质量无关紧要。边缘用于表示场景中的负空间(例如另一个实体内的空心点)或不可交叉的,不可见的薄边界。例如,边缘经常用于表示场景的边界。 边和体积之间的主要区别在于边缘允许在其自身边界内移动,而体积被视为实体对象。 如果边缘通过其他方式移动,则它们仅与卷交互,而不与其他边缘交互。
根据以上信息,如果您阅读了使用 bodyWithEdgeFromPoint:toPoint:的方法的文档,您将看到您正在创建一个“基于Edge的”物理主体。
返回值
一个新的基于边缘的物理团体。
<强>讨论强>
边缘没有体积或质量,并且始终被视为动态属性等于NO。边缘可能只与基于体积的物理体碰撞。
要使碰撞起作用,必须确保边缘与基于体积的物理体碰撞。每个物理体形状创建方法都记录了它正在创建的形状的类型。
如果 使用与边缘碰撞的基于体积的物理主体,则另一种可能性可能是由于所涉及对象的大小或速度。再一次,阅读Apple的文档就清楚了。
为小型或快速移动的物体指定高精度碰撞: 当Sprite Kit执行碰撞检测时,它首先确定场景中所有物理实体的位置。然后它确定是否发生了冲突或联系。这种计算方法很快,但有时会导致错过碰撞。一个小小的身体可能移动得如此之快,以至于它完全穿过另一个物理身体而没有动画帧,两者相互接触。
如果您有必须碰撞的物理实体,您可以提示Sprite Kit使用更精确的碰撞模型来检查交互。这种型号比较贵,所以应该谨慎使用。当任一机构使用精确碰撞时,会联系并测试多个移动位置,以确保检测到所有接触
ship.physicsBody.usesPreciseCollisionDetection = YES;
其他可能性也可能使碰撞陷入混乱,例如您分配给物理主体的路径的错误位置信息。重要的是要了解当您设置节点的路径时,使用节点的本地坐标系设置形状。重要的是要记住Sprite Kit中的原点位于左下角(不是UIKit的左上角),当您为节点的物理主体指定路径时,路径相对于节点的锚点放置
例如:
SKShapeNode *ball = [[SKShapeNode alloc] init];
CGRect ballFrame = CGRectMake(-25.0, -25.0, 50.0, 50.0);
[ball setPath:[UIBezierPath bezierPathWithOvalInRect:ballFrame].CGPath];
[ball setPosition:CGPointMake(100.0, 450.0)];
[ball setFillColor:[UIColor redColor]];
[ball setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:25.0]];
如果我将“ballFrame”的原点设置为(0,0),那么半径为25.0的物理体的圆圈将与球的形状不一致,如物理学的左下角在球的局部坐标系中,体将被放置在球的锚点处,即点x = 0和y = 0。