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 中的无限滚动背景的主要内容,如果未能解决你的问题,请参考以下文章