Рендеринг сотен "блочных" изображений -vs- Частично рендеринг "карты" блоков - PullRequest
0 голосов
/ 19 мая 2010

Похоже, что ни одно из этих решений не устраняет задержку, связанную с рендерингом изображений на экране (как из .png, так и с использованием CG).

Существует сетка блоков размером 28x16, каждый из которых имеет размер 16x16 пикселей, и в некоторых точках игры около половины из них должны изменить свое изображение из-за изменения состояния. Наличие каждого блока в качестве подпредставления основного вида вызывает задержку, когда половина из них должна индивидуально изменить свое изображение (либо из .png, либо с помощью CG).

Я попытался создать один вид "карты" с drawRect: метод:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);

// width and height are defined as the width and height of the grid (28x16 for iPhone)
for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
        // states[] is an enum instance variable that holds the states of each block in the map (state determines image)
        if (states[(x * height) + y] == PXBlockStateEmpty) {
            CGContextSetFillColorWithColor(context, [UIColor colorWithRed:153.0/255.0 green:153.0/255.0 blue:153.0/255.0 alpha:0.5].CGColor);
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
            CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
            CGContextDrawPath(context, kCGPathFillStroke);
        } else if (states[(x * height) + y] == PXBlockStateSolid || states[(x * height) + y] == PXBlockStateSolidEdge) {
            CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:102.0/255.0 alpha:0.9].CGColor);
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
            CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
            CGContextDrawPath(context, kCGPathFillStroke);
        } else if (states[(x * height) + y] == PXBlockStateBuilding) {
            CGContextSetFillColorWithColor(context, [UIColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:0.5].CGColor);
            CGContextFillRect(context, CGRectMake(x * 16, y * 16, 16, 16));
        }
    }
}

Таким образом, мое решение состояло в том, чтобы вызвать setNeedsDisplayInRect: на карте, передав кадр (прямоугольник 16x16) блока, состояние которого изменилось. Я неправильно использую setNeedsDisplayInRect: или это просто неэффективный способ сделать это?

Оба варианта (одно подпредставление против сотен подпредставлений) немного отстают от игры, когда большая часть доски заполнена другим изображением, а второе решение, в частности, отстает всякий раз, когда требуется обновить ЛЮБОЙ образ блока.

Есть идеи? Спасибо за вашу помощь!

1 Ответ

1 голос
/ 19 мая 2010

Вызов setNeedsDisplayInRect: влияет на аргумент drawRect: но в остальном он такой же, как setneedsDisplay. Прямоугольник drawRect: receive - это объединение всех грязных прямоугольников. Если вы рисуете только контент, который пересекает этот прямоугольник, оставляя другой контент без изменений, вы можете увидеть улучшение скорости. Судя по фрагменту кода выше, вы каждый раз рисуете каждый тайл. Поскольку это объединение, вы можете также отслеживать грязные плитки отдельно и рисовать только грязные плитки. В этом случае вызовите CGContextClearRect для отдельных плиток вместо очистки всего контекста, если только они не загрязнены.

CGContextAddRect добавляет прямоугольник к пути, который будет нарисован. Поскольку вы рисуете путь в каждом цикле без начала нового пути, вы перерисовываете области по мере прохождения цикла. Вероятно, было бы быстрее использовать CGContextFillRect и CGContextStrokeRect вместо пути.

Создание каждой плитки отдельным UIView влечет за собой больше накладных расходов, чем рисование в целом. Вы должны быть в состоянии получить лучшую скорость от этого метода, как только изломы обработаны.

...