Reputation: 111
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?
Upvotes: 0
Views: 159
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