8

有没有人成功地使用 JSTilemap 仅加载可见图块?我问的原因是因为我的地图太大而无法一次加载,我想单独加载段或只动态加载当前在屏幕上可见的图块。

我不想使用 KoboldKit。

编辑:令人兴奋的更新。Steffan 和 Marcus 正在 TilemapKit.com 上开发一个漂亮的工具包。迫不及待地想把钱扔给他们。

4

2 回答 2

2

我过去使用过分段地图方法。这适用于侧面滚动地图,您只需在侧面添加另一块。它也适用于需要侧面和底部或顶部的较大地图。

使用这种方法的另一个好处是,如果需要,可以在每次加载新地图时随机化地图部分。这消除了特定级别的“相同的旧地图”。

对于下面的代码示例,我使用相同大小的地图部分,宽度为 1280,并排放置。以下是涉及的步骤:

在 Tiled 应用程序中创建相同大小的地图部分。为每个地图部分指定一个以数字结尾的唯一名称。像这样的东西:MyMap-0、MyMap-1、MyMap-2 等等。

创建一个可变数组来保存您的地图部分。让我们称之为mapSectionsArray

创建一个名为的 float ivarmapOffsetX并将其初始值设置为零。

如果您要创建包含 10 个部分的静态地图,请使用以下代码:

for (int i = 0; i < 10; i++) {
    NSString *myString = [NSString stringWithFormat:@"MyMap-%d.tmx",i];
    JSTileMap *tiledMap = [JSTileMap mapNamed:myString];
    tiledMap.position = CGPointMake(mapOffsetX, 0);
    tiledMap.zPosition = 100;

    [worldNode addChild:tiledMap];
    [mapSectionsArray addObject:tiledMap];
    mapOffsetX += 1280;
}

如果您要创建包含 10 个部分的随机地图,请使用以下代码:

// create an array with the total number of sections created.
// in this example I have created 30 sections in total
// I make sure not to load the same section twice
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:@"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", @"13", @"14",@"15", @"16", @"17", @"18", @"19", @"20", @"21", @"22", @"23", @"24", @"25", @"26", @"27", @"28", @"29", nil];

for (int i = 0; i < 10; i++) {
    int r1 = arc4random() % [myArray count];

    NSString *myString = [NSString stringWithFormat:@"MyMap-%@.tmx",[myArray objectAtIndex:r1]];
    JSTileMap *tiledMap = [JSTileMap mapNamed:myString];
    tiledMap.position = CGPointMake(mapOffsetX, 0);
    tiledMap.zPosition = 100;

    [worldNode addChild:tiledMap];
    [mapSectionsArray addObject:tiledMap];
    mapOffsetX += 1280;

    [myArray removeObjectAtIndex:r1];
}

要在地图的对象层中加载项目,您可以执行以下操作:

-(void)loadMapObjects {
    float xOffset;
    xOffset = 0;

    for (int i = 0; i < [mapSectionsArray count]; i++) {
        TMXObjectGroup *group = [[mapSectionsArray objectAtIndex:i] groupNamed:@"ObjectLayerName"];

        NSArray *arrayObjects = [group objectsNamed:@"objectName"];
        for (NSDictionary *dicObj in arrayObjects) {
            SKNode *myNode = [SKNode node.....];
            CGFloat x = [dicObj[@"x"] floatValue];
            CGFloat y = [dicObj[@"y"] floatValue];
            myNode.position = CGPointMake(x+xOffset, y);

            [worldNode addChild:myNode];
        }
    xOffset += 1280;
}

在更新方法中,您可以根据玩家的位置添加或删除选定的地图部分,如下所示:

// the exact values are determined by your view's size
// and map section's width
left = player.position.x - 1500;
right = player.position.x + 1500;
up = player.position.y + 1000;
down = player.position.y - 1000;

    for(JSTileMap *object in mapSectionsArray) {

        if((object.position.x > left) && (object.position.x < right) && (object.position.y > down) && (object.position.y < up)) {
            if(object.parent == nil) {
                [worldNode addChild:object];
            }
        } else {
            if(object.parent != nil) {
                [object removeFromParent];
            }
        }
    }

根据玩家的位置,地图部分被删除或添加到 worldNode 父级。

另一个优化是当它们不在视图中时,也可以(从父级)移除具有物理实体的对象。根据您的游戏设计和逻辑,这可能可行,也可能不可行。

您可以在更新方法中处理此问题:

left = player.position.x - 1500;
right = player.position.x + 1500;
up = player.position.y + 1000;
down = player.position.y - 1000;

for(SKSpriteNode *object in mapItemsArray) {
    if((object.position.x > left) && (object.position.x < right) && (object.position.y > down) && (object.position.y < up)) {
        if(object.parent == nil) {
            [worldNode addChild:object];
        }
    } else {
        if(object.parent != nil) {
            [object removeFromParent];
        }
    }
}
于 2015-04-11T13:26:53.780 回答
2

以前已经这样做过。看看这里如何让 JSTileMap 做你所要求的。

https://github.com/fattjake/JSTileMap/commit/01b5bacc8c5ccc1099e020276d204ba439a6d06c

希望有帮助!

稍后更新:初步研究表明这可能不是要走的路,让 spriteKit 为您处理优化。看到这个小讨论: https ://github.com/slycrel/JSTileMap/issues/28

于 2014-05-09T06:09:14.907 回答