Как создать альфа-маску в iOS с помощью набора спрайтов

Эффект, которого я пытаюсь достичь, это наличие круга света в области темноты. Эффект аналогичен таковому в играх покемонов, когда вы находитесь в темной пещере и имеете только ограниченное зрение, окружающее вас. Из того, что я пробовал и читал, я не смог создать маску для узлов в наборе спрайтов с альфа-уровнями. Все маски, которые мне удается создать, имеют твердый край и в основном просто обрезаются. Читая на странице для разработчиков Apple о SKCropNode, который имеет свойство maskNode, он говорит: "Если пиксель в маске имеет альфа-значение менее 0,05, пиксель изображения маскируется". Это, к сожалению, звучит для меня так, что пиксели будут либо полностью замаскированы, либо полностью включены, без альфа-значений между ними. Если то, что я пытаюсь сказать, было трудно понять, вот изображение того, чего я достиг: https://www.dropbox.com/s/y5gbk8qvuq4ynh0/iOS%20Simulator%20Screen%20shot%20Jan%2020%2C%202014%201.06.23%20PM.png

и вот изображение того, чего я хотел бы достичь: https://www.dropbox.com/s/wtwfdi1mjs2n8e6/iOS%20Simulator%20Screen%20shot%20Jan%2020%2C%202014%201.05.54%20PM.png

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

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

SKSpriteNode *background = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(500, 500)];
    background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    SKCropNode *cropNode = [[SKCropNode alloc] init];
    SKNode *area = [[SKNode alloc] init];

    int x = 65; //radius of the circle

    _circleMask = [[SKShapeNode alloc ]init];
    CGMutablePathRef circle = CGPathCreateMutable();
    CGPathAddArc(circle, NULL, 0, 0, x/2, 0, M_PI*2, YES);
    _circleMask.path = circle;
    _circleMask.lineWidth = x*2;
    _circleMask.strokeColor = [SKColor whiteColor];
    _circleMask.name=@"circleMask";
    _circleMask.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

//Here is where I just added in the gradient circle To give the desired appearance, but this isn't necessary to the code
    //_circleDark = [SKSpriteNode spriteNodeWithImageNamed:@"GradientCircle"];
    //_circleDark.position = [cropNode convertPoint:_circleMask.position fromNode:area];

    [area addChild:_circleMask];

    [cropNode setMaskNode:area];
    [cropNode addChild:background];
    //[cropNode addChild:_circleDark];

    [self addChild:cropNode];

Этот метод также позволил мне перемещать круги, открывая различные части изображения позади него, что я и хочу. Для этого я просто настроил его на изменение _circleMask.position, когда пользователь нажимает на экран.

Кроме того, просто чтобы прояснить ситуацию на случай, если кто-то запутался, черный цвет - это просто фоновый цвет сцены, поверх которой находится картинка, а затем круг является частью узла маски.

2 ответа

Очень простой (и, возможно, менее... или более производительной) версией этого было бы просто добавить SKSpriteNode сверху, на котором ваша виньетка на прозрачном фоне. Другими словами, если смотреть в Photoshop, вы увидите уменьшающуюся шахматную доску, видимую в круге, когда вы идете от центра к центру, в конечном итоге отображая сплошной черный цвет. Когда изображение PNG используется в вашем приложении, эта прозрачность будет сохранена при компоновке двух спрайтов.

У меня есть идея... Я надеюсь, что это поможет.

Создайте PNG с желаемым градиентом от белого до черного без прозрачности.

Используйте отдельный узел спрайта с png для каждого нужного источника света и добавьте их все в узел SKEffectNode или SKCropNode. Неважно, что, поскольку они оба отображаются в отдельном контексте. Установите каждый узел спрайта в режим смешивания экрана.

Затем, при добавлении родительского SKEffectNode или SKCropNode в сцену, установите его в режим умножения смешивания.

В конце скрининг прекрасно объединит "огни", а умножение сделает белую область прозрачной.

Другие вопросы по тегам