user717452
user717452

Reputation: 111

SpriteKit Scrolling Bottom Has Gap When Loops

In my app, I have an image that acts as the ground, and scrolls along the bottom. I initialize and scroll it with:

 -(void)initalizingScrollingBackground
    {
        for (int i = 0; i < 2; i++)
        {
            SKSpriteNode *bg = [SKSpriteNode spriteNodeWithImageNamed:@"Bottom_Scroller"];
            bg.zPosition = BOTTOM_BACKGROUND_Z_POSITION;
            bottomScrollerHeight = bg.size.height;
            bg.position = CGPointMake((i * bg.size.width) + (bg.size.width * 0.5f) - 1, bg.size.height * 0.5f);
            bg.name = @"bg";
            bg.physicsBody = [SKPhysicsBody bodyWithTexture:bg.texture size:bg.texture.size];


            bg.physicsBody.categoryBitMask = bottomBackgroundCategory;


            bg.physicsBody.contactTestBitMask = flappyBirdCategory;


            bg.physicsBody.collisionBitMask = 0;


            bg.physicsBody.affectedByGravity = NO;
            [self addChild:bg];
        }
    }

- (void)moveBottomScroller
{
    [self enumerateChildNodesWithName:@"bg" usingBlock: ^(SKNode *node, BOOL *stop)
     {
         SKSpriteNode * bg = (SKSpriteNode *) node;
         CGPoint bgVelocity = CGPointMake(-BG_VELOCITY, 0);
         CGPoint amtToMove = CGPointMultiplyScalar(bgVelocity,_dt);
         bg.position = CGPointAdd(bg.position, amtToMove);

         //Checks if bg node is completely scrolled of the screen, if yes then put it at the end of the other node
         if (bg.position.x + bg.size.width * 0.5f <= 0)
         {
             bg.position = CGPointMake(bg.size.width*2 - (bg.size.width * 0.5f) - 2,
                                       bg.position.y);
         }
     }];
}

However, after it scrolls for so long, it shows a gap in it, as shown below. How can I fix this?

enter image description here

Upvotes: 0

Views: 159

Answers (1)

gzafra
gzafra

Reputation: 496

What I'd do is:

// This would go in the init or didMoveToView method of your scene
const NSUInteger numBgs = 3;
for (NSUInteger i = 0; i < numBgs; i++) {
    CGFloat color = 0.2f * i;
    SKSpriteNode *bg = [SKSpriteNode spriteNodeWithColor:[UIColor colorWithRed:color green:color blue:color alpha:1.0] size:CGSizeMake(512, 300)];
    bg.anchorPoint = CGPointMake(0.5, 0); 
    bg.position = CGPointMake((i * bg.size.width) + (bg.size.width * 0.5f), CGRectGetMinY(self.frame));
    bg.name = @"bg";
    [self addChild:bg];

    if (i == numBgs-1) { // Means it's last bg on the right
        lastBg = bg;
    }
}

[self enumerateChildNodesWithName:@"bg" usingBlock:^(SKNode *node, BOOL *stop) {
    SKSpriteNode * bg = (SKSpriteNode *) node;

    //Checks if bg node is completely scrolled of the screen, if yes then put it at the end of the other node
    if (bg.position.x + bg.size.width * 0.5f <= 0)
    {
        bg.position = CGPointMake(lastBg.position.x + bg.frame.size.width,
                                  bg.position.y);
        lastBg = bg;
    }


    CGPoint bgVelocity = CGPointMake(-BG_VELOCITY, 0);
    CGPoint amtToMove = CGPointMultiplyScalar(bgVelocity,_dt);
    bg.position = CGPointAdd(bg.position, amtToMove);

}];

Where lastBg is an instance variable that points to the bg located at the top most right so that re-positioning is always going to be relative to this sprite.

Other things you can try are switching the check of the position before the re-positioning (as I did in the example) and also remove the check out of the enumerate block and do it independently of the re-positioning.

I used to do like in the example and it worked fine. Let me know how it does.

Upvotes: 2

Related Questions