问题
你的根本问题在于,你在蓝色圆之间没有留下任何空间。让我们假设圆的半径为30,顶部圆的y位置为400。
您用于定位中间圆的数学公式可能是 topCircle.position.y - (topCircle.height + middleCircle.height) / 2
。由于您的所有圆都具有相同的半径(在我们的示例中为30),因此您可能将其简化为 topCircle.y - CIRCLE_DIAMETER
。如果您将圆圈绝对定位,那么这可能是您在脑海中执行的计算。
无论采用哪个公式,当您输入数字时,第二个圆的y位置都将为340。
第一个公式:400 - (60 + 60) / 2 = 340
第二个公式:400 - 60 = 340
(注意:第一个公式更加灵活,可以让您使用任何大小的圆,而不是固定大小的圆)
问题就在这里。现在应该清楚了,顶部圆的底部占据了与中间圆的顶部相同的空间。
顶部圆:400 - 30 = 370
中间圆:340 + 30 = 370
之间的空间:|370 - 370| = 0
两个物理体试图占据同一点,因此合并成一个物体,导致您看到的行为。
解决方案
说了这么多,如果简单地在圆之间添加一个或更少的空间,您将得到所需的行为。
(注意:还要确保每个圆的物理体的恢复设置为1 )
这适用于任意数量的圆。以下是一个简单的示例场景,其中有1个圆与4个其他圆接触,并展现了此行为。我在iPhone 6上运行了它:
#import "GameScene.h"
@interface GameScene()
@property (strong, nonatomic) NSArray *nodes;
@end
@implementation GameScene
#pragma mark - View Lifecycle
-(void)didMoveToView:(SKView *)view
{
self.backgroundColor = [SKColor blackColor];
[self createNodes];
[self positionNodes];
[self addNodes];
}
#pragma mark - Setup
- (void)createNodes
{
self.nodes = @[[SKSpriteNode spriteNodeWithImageNamed:@"circle"],
[SKSpriteNode spriteNodeWithImageNamed:@"circle"],
[SKSpriteNode spriteNodeWithImageNamed:@"circle"],
[SKSpriteNode spriteNodeWithImageNamed:@"circle"],
[SKSpriteNode spriteNodeWithImageNamed:@"circle"]];
for(SKSpriteNode *node in self.nodes)
{
node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:30];
node.physicsBody.affectedByGravity = NO;
node.physicsBody.restitution = 1;
}
}
- (void)positionNodes
{
SKSpriteNode *node = self.nodes.firstObject;
node.position = CGPointMake(300, 400);
for(NSInteger i = 1; i < self.nodes.count - 1; i++)
{
SKSpriteNode *prevNode = node;
node = self.nodes[i];
node.position = CGPointMake(300, prevNode.position.y - (prevNode.frame.size.height + node.frame.size.height) / 2 - 1);
}
node = self.nodes.lastObject;
node.position = CGPointMake(300, 100);
}
- (void)addNodes
{
for(SKSpriteNode *node in self.nodes)
{
[self addChild:node];
}
}
#pragma mark - Touch Events
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
SKSpriteNode *node = self.nodes.lastObject;
[node.physicsBody applyImpulse:CGVectorMake(0, 20)];
}
@end