SpriteKit - 从非常大的图像(640 x 6000)创建滚动背景

时间:2014-06-15 16:47:30

标签: ios objective-c sprite-kit

我已成功将我的大图像(640 x 6000)剪切成20张,但无法弄清楚使用这些图像的最佳方式是什么。

我唯一想到的是创建20个精灵并将它们全部添加到屏幕上并使用相同的移动动作,以便它们显示为滚动。

但这不会只是使用相同数量的内存来将整个图像加载到内存中吗?

我查看了精灵工具包文档,但不明白它是如何完成的。

有人可以帮忙吗?

由于

1 个答案:

答案 0 :(得分:3)

我建议跳过滚动操作并改用update方法。还有一种方法可以同时只有几个背景部分。

首先,您需要创建纹理图集并在那里添加所有这些图像。 其次,您需要在场景中创建两个属性:

SKSpriteNode *firstNode;
SKSpriteNode *secondNode;

我还建议将所述图集添加为实例变量,如
SKTextureAtlas *atlas;

在场景的init方法或您的其他设置方法中,您需要创建和定位这些节点。另外,不要忘记在此之前创建纹理图集变量。

self.firstNode = [[SKSpriteNode alloc] initWithTexture:[self.atlas textureNamed:@"texture1"]];
self.secondNode = [[SKSpriteNode alloc] initWithTexture:[self.atlas textureNamed:@"texture2"]];

通常在这种情况下,我将这些精灵的锚点更改为CGPointMakeZero,以简化定位计算。这可以这样做:

self.firstNode.anchorPoint = CGPointZero;
self.secondNode.anchorPoint = CGPointZero;

它有助于精灵的(0,0)点是精灵的左下角。

现在我们可以根据需要将精灵添加到我们的世界,直接添加到场景或中间世界节点。

self.firstNode.position = CGPointMake(0, 0); // or CGPointZero
self.secondNode.position = CGPointMake(self.firstNode.size.width, 0);

现在我们有两个节点相互跟随。

我们如何滚动?我们需要更改更新方法。我们需要创建新属性CFTimeInterval lastUpdate,我们需要它来存储自上次更新以来经过的时间,并且我们可以计算移动节点所需的像素数量。

-(void)update:(CFTimeInterval)currentTime {

    if (!self.lastUpdate) {
        self.lastUpdate = currentTime;
        self.secondsCounter = 0;
        return;
    }

    double delta = currentTime - self.lastUpdate;
    self.lastUpdate = currentTime;

[self updateGroundScrollingWithDelta:delta];
}

这是实际滚动节点的方法(你需要在别处定义一些moveSpeed或者只是将它改为某个常量):

    - (void)updateGroundScrollingWithDelta:(double)delta
    {

        self.firstNode.position = CGPointMake(self.firstNode.position.x - delta * moveSpeed, self.firstNode.position.y);
        self.secondNode.position = CGPointMake(self.secondNode.position.x - delta * moveSpeed, self.secondNode.position.y);

        if (self.firstNode.position.x < -self.firstNode.size.width) {

            self.firstNode.position = CGPointMake(self.secondNode.position.x + self.secondNode.size.width - 1, self.firstNode.position.y);

// here you need to change the texture of your node

        }

        if (self.secondNode.position.x < -self.secondNode.size.width) {

            self.secondNode.position = CGPointMake(self.firstNode.position.x + self.firstNode.size.width - 1, self.secondNode.position.y);

// here you need to change the texture of your node

        }
    }

在这个方法中,我们将节点移动一定数量的像素,然后检查 - 如果节点离左边太远,并且不可见,我们将节点附加到另一个节点的末尾,所以我们滚动似乎浑然一体。
在某处,您需要更改精灵的纹理,如评论中所述。 为了跟踪纹理,我建议制作一个实例变量int counter。显然它应该从2开始,因为我们已经在两个节点上安排了纹理编号0和1。

您可以使用它来查看下一个纹理。所以在这里我建议一种方法来获得下一个纹理:

- (SKTexture *)nextBackgroundTexture
{
    NSString *nextName = [NSString stringWithFormat:@"myTexture%d", self.counter];
    self.counter++;
    return [self.atlas textureNamed:nextName];
}

所以现在你只需要在需要时更新计数器并交换纹理。 正如我所说,你可以将这些行放在方法的注释部分来滚动节点:

self.firstNode.texture = [self nextBackgroundTexture];

self.secondNode.texture = [self nextBackgroundTexture];

这样你在内存中只有两个纹理,滚动就可以了。 (实际上这不是真的,因为Sprite Kit会缓存使用过的纹理,但希望将来可以释放它们。)

希望这会有所帮助。

P.S。实际上在重新阅读你的问题之后,我发现你需要垂直滚动,改变这很简单,你需要以不同的方式定位节点,使用y坐标和节点高度而不是宽度来找到位置。

同样在滚动时更改Y值而不是X值。

我将此作为练习留给你。