Тестирование попаданий с помощью CALayer с использованием альфа-свойств содержимого CALayer - PullRequest
6 голосов
/ 31 мая 2010

Я пишу игру для Mac, используя Какао. В настоящее время я внедряю тестирование на попадание и у меня есть основания полагать, что CALayer предлагает тестирование на попадание, но, похоже, не реализует альфа-свойства. Поскольку у меня иногда много CALayers, накладываемых друг на друга, мне действительно нужно найти способ определить, что пользователь действительно хотел щелкнуть.

Я думаю, что если бы я мог как-то получить массив, который содержит указатели на все CALayers, которые содержат точку щелчка, я мог бы как-то отфильтровать их. Однако единственный способ, которым я до сих пор создал массив, это:

NSMutableArray* anArrayOfLayers = [NSMutableArray array];
    for (CALayer* aLayer in mapLayer.sublayers)
    {
        if ([aLayer containsPoint:mouseCoord])
            [anArrayOfLayers addObject:aLayer];
    }

Затем сортируйте массив по z-значениям CALayer, затем проходите проверку, является ли пиксель в местоположении альфа или нет. Однако, между сортировкой и альфа-проверкой это кажется невероятным скачком производительности. (Как бы вы проверили альфу?)

Есть ли способ сделать это?

1 Ответ

10 голосов
/ 15 октября 2010

Я наткнулся на то, что почесывая голову над подобной проблемой, - CALayer использует containsPoint: при отправке hitTest:

Его поведение по умолчанию состоит в том, чтобы проверять границы, но мы можем переопределить и заставить его проверять альфа-канал, и просто использовать встроенное тестирование CALayer для обработки остальных:

- (BOOL) containsPoint:(CGPoint)p 
{
    return CGRectContainsPoint(self.bounds, p) && !ImagePointIsTransparent(self.contents, p)) return YES;
}

Существует обсуждение тестирования альфа-канала одного пикселя на Получение значения альфа-пикселя для UIImage

Это сработало для моих целей:

static BOOL ImagePointIsTransparent(CGImageRef image, CGPoint p)
{
    uint8_t alpha;

    CGContextRef context = CGBitmapContextCreate(&alpha, 1, 1, 8, 1, NULL, kCGImageAlphaOnly);
    CGContextDrawImage(context, CGRectMake(-p.x, -p.y, CGImageGetWidth(image), CGImageGetHeight(image)), image);
    CGContextRelease(context);

    return alpha == 0;
}

(Если вы используете renderInContext: для рисования в CALayer, а не устанавливаете его свойство содержимого, то это будет более сложным. Это может быть полезно в этом случае: http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/)

...