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

标签 ios objective-c sprite-kit

我已成功将大图像 (640 x 6000) 分割成 20 block ,但不知道使用这些图像的最佳方式是什么。

我唯一的想法是创建 20 个 Sprite ,并使用相同的移动 Action 将它们全部添加到屏幕上,以便它们看起来在滚动。

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

我浏览了 sprite 套件文档,但不明白它是如何完成的。

有人可以帮忙吗?

谢谢

最佳答案

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

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

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"]];

通常在这种情况下,我会将这些 Sprite 的 anchor 更改为 CGPointMakeZero,以简化定位计算。这可以像这样完成:

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

它在某种程度上有帮助, Sprite 的 (0,0) 点是 Sprite 的左下角。

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

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

        }
    }

在此方法中,我们将节点移动一定数量的像素,然后检查 - 如果该节点距离左侧太远并且不可见,我们将该节点附加到另一个节点的末尾,因此我们的滚动似乎无缝。
在某个地方,您将需要更改 Sprite 的纹理,如评论中所述。 为了跟踪纹理,我建议创建一个实例变量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 缓存了使用过的纹理,但希望它能在将来的某个时候释放它们)。

希望这有帮助。

附注实际上,在重新阅读你的问题后,我发现你需要垂直滚动,改变这一点相当简单,你需要以不同的方式在开始时定位节点,使用 y 坐标和节点高度而不是宽度来查找位置。

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

我把这个作为练习留给你。

关于ios - SpriteKit - 从非常大的图像(640 x 6000)创建滚动背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24231865/

相关文章:

ios - ins SpriteKit, "select"我的手指在移动时触摸的所有 Sprite

ios - 如何自定义 UITableView 的 Separator View?

ios - CocoaPods 问题

ios - 无法在 Realm 中存储 NSDate

objective-c - 如何在 obj-c 中交换两个数组

function - Swift 中的全局函数调用?如何?

ios - 将数据从磁盘发送到服务器而不加载到 iOS 上的 ram

iphone - ASIHTTPRequest completionBlock + ARC

ios - 滚动时以曲线/圆弧路径移动 View

ios - 使用 spritekit 为 2d 平台游戏添加移动平台的轻松进出