SpriteKit中的大型无缝滚动背景?

时间:2014-07-16 14:04:07

标签: xcode loops background sprite-kit

好的,所以我对SpriteKit很新,但到目前为止,使用它还是很有趣。我正在寻找一种无休止地拥有大型滚动背景循环的方法。我已经将我的背景划分为小块,让SK根据需要调用它,使用以下代码:

    for (int nodeCount = 0; nodeCount < 50; nodeCount ++) {
    NSString *backgroundImageName = [NSString stringWithFormat:@"Sky_%02d.gif", nodeCount +1];
    SKSpriteNode *node = [SKSpriteNode spriteNodeWithImageNamed:backgroundImageName];
    node.xScale = 0.5;
    node.yScale = 0.5;
    node.anchorPoint = CGPointMake(0.0f, 0.5f);
    node.position = CGPointMake(nodeCount * node.size.width, self.frame.size.height/2);
    node.name = @"skyBG";

我可以在update中移动整个块,但我无法让它无缝循环。或者根本就是这个问题。我已经尝试过在这里其他地方建议的方法,它采用背景的副本并将其带到另一端以给出无缝循环的外观,并且这里没有骰子。我也尝试将其添加到上面代码的末尾,我希望这可能会起作用:

        if (nodeCount == 49)
    {
        nodeCount = 0;
    }

但这只是导致模拟器挂起,所以我认为它无意中创建了一个循环或其他东西。任何帮助都会很棒!我觉得有一个简单的解决办法,但我只是没有到达那里...感谢一帮,伙计们!

更新

这是我正在使用的代码,用于滚动背景,效果很好:

-(void)update:(CFTimeInterval)currentTime {

_backgroundNode.position = CGPointMake(_backgroundNode.position.x - 1, _backgroundNode.position.y);

}

总而言之:我有一个动人的背景,但由于背景的大小,让它无缝循环一直很有挑战性。如果我有什么可以帮助澄清,请告诉我!非常感谢

2 个答案:

答案 0 :(得分:1)

这只是您可以用来实现滚动背景的逻辑示例。它绝不是最终的或理想的实现,而是一个概念性的例子。

这是一个简单的滚动类:

// Scroller.h

#import <SpriteKit/SpriteKit.h>

    @interface Scroller : SKNode
    {
       // instance variables
        NSMutableArray *tiles;  // array for your tiles
        CGSize tileSize;    // size of your screen tiles
        float scrollSpeed; // speed in pixels per second
    }

    // methods 
    -(void)addTiles:(NSMutableArray *)newTiles;
    -(void)initScrollerWithTileSize:(CGSize)scrollerTileSize scrollerSpeed:(float)scrollerSpeed;
    -(void)update:(float)elapsedTime;

    @end

实施:

// Scroller.m 

#import "Scroller.h"

@implementation Scroller


-(instancetype)init
{
    if (self = [super init])
    {
        tiles = [NSMutableArray array];
    }

    return self;
}


-(void)addTiles:(NSMutableArray *)newTiles
{
    [tiles addObjectsFromArray:newTiles];
}

-(void)initScrollerWithTileSize:(CGSize)scrollerTileSize scrollerSpeed:(float)scrollerSpeed
{
    // set properties
    scrollSpeed = scrollerSpeed;
    tileSize = scrollerTileSize;

    // set initial locations of tile and set their size
    for (int index = 0; index < tiles.count; index++)
    {
        SKSpriteNode *tile = tiles[index];

        //set anchorPoint to bottom left
        tile.anchorPoint = CGPointMake(0, 0);

        // set tilesize
        // this implementation requires uniform size
        [tile setSize:tileSize];

        //calcuate and set initial position of tile
        float startX = index * tileSize.width;
        tile.position = CGPointMake(startX, 0);

        //add child to the display list
        [self addChild:tile];
    }
}

-(void)update:(float)elapsedTime
{
    //calculate speed for this frame
    float curSpeed = scrollSpeed * elapsedTime;

    // iterate through your screen tiles
    for (int index = 0; index < tiles.count; index++)
    {
        SKSpriteNode *tile = tiles[index];

        // set new x location for tile
        tile.position = CGPointMake(tile.position.x - curSpeed, 0);

        // if new location is off the screen, move it to the far right
        if (tile.position.x < -tileSize.width)
        {
            // calculate the new x position based on number of tiles an tile width
            float newX = (tiles.count -1) * tileSize.width;
            // set it's new position
            tile.position = CGPointMake(newX, 0);
        }
    }

}

在场景中,启动滚动条:

-(void)initScroller
{
    // create an array of all your textures
    NSMutableArray *tiles = [NSMutableArray array];
    [tiles addObject:[SKSpriteNode spriteNodeWithTexture:skyTexture]];
    [tiles addObject:[SKSpriteNode spriteNodeWithTexture:skyTexture]];
    [tiles addObject:[SKSpriteNode spriteNodeWithTexture:skyTexture]];
    [tiles addObject:[SKSpriteNode spriteNodeWithTexture:skyTexture]];

    // create scroller instance (ivar or property of scene)
    scroller = [[Scroller alloc]init];

    // add the tiles to the scroller
    [scroller addTiles:tiles];

    // init the scroller with desired tile size and scroller speed
    [scroller initScrollerWithTileSize:CGSizeMake(1024, 768) scrollerSpeed:500];

    // add scroller to the scene
    [self addChild:scroller];

}

在场景更新方法中:

-(void)update:(CFTimeInterval)currentTime 
{

    float elapsedTime = .0166; // set to .033 if you are locking to 30fps

    // call the scroller update method
    [scroller update:elapsedTime];
}

同样,这个实现非常简单,是一个概念性的例子。

答案 1 :(得分:0)

我目前正在开发一个用于图块滚动的库,正在使用类似于原型提供的解决方案,但使用Tableview数据源模式来请求节点。看看它:

RPTileScroller

我会尽一切努力使其成为最有效的,但请注意,我不是游戏开发者。我尝试用我的iPhone 5和10x10像素的随机颜色瓷砖,并以60 fps的稳定运行。