SpriteKit 中的无限滚动背景

Posted

技术标签:

【中文标题】SpriteKit 中的无限滚动背景【英文标题】:Endless Scrolling Background in SpriteKit 【发布时间】:2014-02-11 13:27:59 【问题描述】:

我正在尝试使用 Apple 的 SpriteKit 制作横向卷轴游戏。当我想做一个无限滚动的背景时,我遇到了这个answer。

实施该解决方案后,它似乎确实可以工作虽然它显着降低了我的 FPS。这可能是因为每帧都重新计算图像位置。

我觉得如果我可以使用一个或多个SKAction 调用来为我处理这个动画会更好,但我不确定如何实现它。

想法?

到目前为止,我在场景类中的代码(不过,这只会使屏幕上的背景动画一次)

- (void)addBackgroundTileAtPoint:(CGPoint)point 

    SKSpriteNode *bg = [SKSpriteNode spriteNodeWithImageNamed:@"background"];
    bg.anchorPoint = CGPointZero;
    bg.position = point;
    bg.name = @"background";
    bg.zPosition = -99;
    [self addChild:bg];

    SKAction *sequence = [SKAction sequence:@[
        [SKAction moveByX:-(bg.size.width * 2) y:0 duration:10],
        [SKAction removeFromParent]
    ]];
    [bg runAction: sequence];

【问题讨论】:

除非滚动是恒定的,否则动作不会对你有任何好处:相同的方向以相同的速度。即便如此,我怀疑行动会明显快于答案实施。虽然如果你只引用两个背景精灵而不是 enumerateByName 可能会更快,这样 SK 就不需要按名称搜索节点图。 您需要在 *sequence 中进行递归调用。即在 [SKAction removeFromParent] 之后,添加 [self addBackgroundTileAtPoint:];,或者您应该使用重复操作而不从超级视图中删除背景 @LearnCocos2D 如果无法采取行动,您是否对优化其他答案解决方案有任何建议,或者您是否有不同的解决方案。在模拟器上运行该答案的解决方案时,FPS 立即从 60 下降到 ~30。 我很确定模拟器将应用程序的帧速率限制在 30fps 左右,所以你看到的速度变慢只是一个副作用,并不是应用程序正在挣扎的迹象。 【参考方案1】:

我在上一个开源项目中针对该特殊需求做了一个名为 SKScrollingNode 的小组件:SprityBird。

即使是 3 或 4 层(视差),FPS 也不是问题,但您可能需要自己尝试一下。

要使用它,您只需像添加任何其他节点一样添加它并给它一个scrollingSpeed likeso :

back = [SKScrollingNode scrollingNodeWithImageNamed:@"back" inContainerWidth:WIDTH(self)];
[back setScrollingSpeed:BACK_SCROLLING_SPEED];
[self addChild:back];

SKScrollingNode.h

@interface SKScrollingNode : SKSpriteNode

@property (nonatomic) CGFloat scrollingSpeed;

+ (id) scrollingNodeWithImageNamed:(NSString *)name inContainerWidth:(float) width;
- (void) update:(NSTimeInterval)currentTime;

@end

SKScrollingNode.m

@implementation SKScrollingNode

+ (id) scrollingNodeWithImageNamed:(NSString *)name inContainerWidth:(float) width

    UIImage * image = [UIImage imageNamed:name];

    SKScrollingNode * realNode = [SKScrollingNode spriteNodeWithColor:[UIColor clearColor] size:CGSizeMake(width, image.size.height)];
    realNode.scrollingSpeed = 1;

    float total = 0;
    while(total<(width + image.size.width))
        SKSpriteNode * child = [SKSpriteNode spriteNodeWithImageNamed:name ];
        [child setAnchorPoint:CGPointZero];
        [child setPosition:CGPointMake(total, 0)];
        [realNode addChild:child];
        total+=child.size.width;
    

    return realNode;


- (void) update:(NSTimeInterval)currentTime

    [self.children enumerateObjectsUsingBlock:^(SKSpriteNode * child, NSUInteger idx, BOOL *stop) 
        child.position = CGPointMake(child.position.x-self.scrollingSpeed, child.position.y);
        if (child.position.x <= -child.size.width)
            float delta = child.position.x+child.size.width;
            child.position = CGPointMake(child.size.width*(self.children.count-1)+delta, child.position.y);
        
    ];
   
@end

【讨论】:

很棒的工作,但随着 ios 9 的发布,使用和 SKSpriteNode 时 enumerateObjectsUsingBlock 会引发不兼容的块指针错误。在玩了之后再搜索一些,我发现下面的帖子解决了这个问题。 ***.com/questions/33584180/…【参考方案2】:

我一直在为无限磁贴滚动器开发一个库,您可以轻松地使用它来创建滚动背景。看看吧:

RPTileScroller

我努力使其尽可能高效,但我不是游戏开发者。我在我的 iPhone 5 上进行了尝试,它具有 10x10 像素的随机颜色图块,并且以稳定的 60 fps 运行。

【讨论】:

以上是关于SpriteKit 中的无限滚动背景的主要内容,如果未能解决你的问题,请参考以下文章

如何为无限滚动的 RecyclerView 绘制背景

libgdx上的无限滚动背景

2d场景背景无限滚动

unity 背景无限循环滚动效果

如何在 spriteKit swift 4 中制作无限背景

如何应用SPRITEKIT的CAMERA实现游戏中的ENDLESS无限循环背景