SKPhysicsBody bodyWithEdgeLoopF​​romRect打破正确的精灵运动

时间:2014-10-08 01:04:28

标签: ios objective-c sprite-kit skphysicsbody

我正在开发一个SpriteKit应用程序,精灵在屏幕上弹跳(iOS 8,iPad,仅横向,Objective-C)。

作为一个测试案例,我有一个精灵从屏幕底部的中间开始,然后以45度向右上行。如果我在屏幕周围没有边缘体,这可以正常工作,但是当我添加边循环时会表现得非常奇怪(注释掉边循环并且它再次起作用)。

self.physicsBody= [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]; 

注意:我在最后添加了一个更新,解释了行为,但没有解释原因。


NSLog显示使用预期帧({{0,0},{768,1024}})创建的边循环,并使用正确的位置和速度添加精灵。

当第一次通过渲染循环调用didSimulatePhysics时,精灵的位置已经移动到屏幕上方四分之一处(横向)并且速度的dx分量已经变为零。精灵然后垂直移动,在屏幕中心〜512点的距离上下弹跳。

换句话说,精灵似乎沿着{384,384}和{384,896}之间的垂直线上下移动,好像边缘循环位于{{384,384},{0, 512}}而不是{{0,0},{768,1024}}。

如果我将精灵的起始位置更改为在此行上,它将从正确的位置开始,但仍会丢失它的x速度分量并保持约束到此行。如果我在该行的y范围内启动精灵但是在该行的x坐标之外,它会立即移动到该行的最近点,并继续相同的行为。

正如其他问题中所建议的那样,我尝试在视图控制器的SKSceneviewWillAppear中展示viewWillLayoutSubviews,但行为是相同的。

我试过对边循环帧进行硬编码 - 没有变化。模拟器和设备上的行为也相同。

我有另一个玩具应用程序,看似相同的代码用于呈现SKScene,设置边循环并生成可以正常工作的精灵。

以下代码来自SKScene子类:

- (id)initWithSize:(CGSize)size;
{
    if (!(self= [super initWithSize:size])) return nil;

    self.physicsWorld.contactDelegate= self;
    self.physicsWorld.gravity= CGVectorMake(0.0, 0.0);

    self.spriteAtlas= [SKTextureAtlas atlasNamed:@"sprites"];

    srandom((unsigned int)time(NULL));

    return self;
}



- (void)didMoveToView:(SKView *)view;
{
    if (!self.contentCreated)
    {
        [self createTestSceneContent];
        self.contentCreated= YES;
    }
}



- (void)createTestSceneContent;
{
    self.backgroundColor= [SKColor whiteColor];
    self.scaleMode= SKSceneScaleModeAspectFit;
    self.name= @"scene";

    CGRect fr= self.frame;

    NSLog(@"bodyWithEdgeLoopFromRect: %@", NSStringFromCGRect(fr));

    // commenting out the following line resolves the issue
    self.physicsBody= [SKPhysicsBody bodyWithEdgeLoopFromRect:fr];

    self.physicsBody.friction= 0.0;
    self.physicsBody.restitution= 1.0;
    self.physicsBody.linearDamping= 0.0;
    self.physicsBody.angularDamping= 0.0;

    SKSpriteNode *ball= [[SKSpriteNode alloc] initWithTexture:[self.spriteAtlas textureNamed:@"ball"]];

    ball.name= @"ball";
    ball.physicsBody= [SKPhysicsBody bodyWithCircleOfRadius:self.size.width / 2.0];
    ball.physicsBody.dynamic= YES;
    ball.physicsBody.mass= 1.0;
    ball.physicsBody.restitution= 1.0;
    ball.physicsBody.friction= 0.0;
    ball.physicsBody.linearDamping= 0.0;
    ball.physicsBody.angularDamping= 0.0;
    ball.physicsBody.affectedByGravity= NO;
    ball.physicsBody.contactTestBitMask= 1;

    ball.position= CGPointMake(self.size.width / 2.0, ball.size.height / 2.0);
    ball.physicsBody.velocity= CGVectorMake(-75.0, 75.0);;

    [self addChild:ball];

    NSLog(@"createTestSceneContent - p= %@, v= %@", NSStringFromCGPoint(ball.position), NSStringFromCGVector(ball.physicsBody.velocity));
}



- (void)didSimulatePhysics;
{
    SKNode *ball= [self childNodeWithName:@"ball"];

    NSLog(@"didSimulatePhysics     - p= %@, v= %@", NSStringFromCGPoint(ball.position), NSStringFromCGVector(ball.physicsBody.velocity));
}

并生成以下日志输出:

  

bodyWithEdgeLoopF​​romRect:{{0,0},{768,1024}}

     

createTestSceneContent - p = {384,15},v = {-75,75}

     

didSimulatePhysics - p = {383.90228,389.04977},v = {0,75}

     

didSimulatePhysics - p = {383.91571,390.29974},v = {0,75}

     

didSimulatePhysics - p = {383.92258,392.17471},v = {0,75}

     

...

     

didSimulatePhysics - p = {383.92499,637.17346},v = {0,75}

     

didSimulatePhysics - p = {383.92499,638.42346},v = {0,75}

     

didSimulatePhysics - p = {383.92499,638.42346},v = {0,-75}

     

didSimulatePhysics - p = {383.92499,637.17346},v = {0,-75}


更新:

经过大量尝试添加不同的边缘体后,我可以解释发生了什么,但不是为什么。

我添加的任何边缘身体似乎从身体所在的位置生效384点。 384是横向iPad屏幕宽度的一半。

例如,如果我在屏幕的左侧添加边缘:

self.physicsBody= [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(0.0, 0.0) toPoint:CGPointMake(0.0, self.size.height)];

精灵会在x == 384时反弹。

因此,对于框架的边缘循环,球被限制在距离屏幕边缘384点的区域内,该区域是屏幕中心256点长的线。在屏幕的每个边缘外设置一个带有矩形384点的边缘循环会产生正确的行为(即精灵在屏幕边缘反弹):

self.physicsBody= [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectInset(self.frame, -384.0, -384.0)];

虽然这个kludge解决了当前的问题,但我仍然想了解为什么会发生这种情况,因为我认为这是一个潜在问题的症状,也会出现在应用程序的其他地方。

任何想法都会非常感激。感谢

0 个答案:

没有答案