Получить/установить цвет пикселя в SKScene, iOS, Swift

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

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

  func getPixelColorAtPoint(point:CGPoint) -> UIColor{

    let pixel = UnsafeMutablePointer<CUnsignedChar>.alloc(4)
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)
    let context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, bitmapInfo.rawValue)

    CGContextTranslateCTM(context, -point.x, -point.y)
    self.layer.renderInContext(context!)
    let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0)

    pixel.dealloc(4)
    return color
  }

Думаю, мне нужно изменить строку '''self.layer....'''. Может ли кто-нибудь помочь мне с этим?

Также я не смог найти никакой информации о том, как задать цвет пикселя непосредственно в UIView или SKScene. Есть идеи?

Кстати: я попытался создать класс UIView/SKNode с размером = 1 пиксель, а затем добавить его в UIView/SKScene, чтобы я мог напрямую установить цвет. Это выполнимо для небольшого количества пикселей. Но я имею дело со многими из них, возможно, с сотнями или тысячами. Это неправильный способ сделать это, так как производительность очень низкая.


person Valar Morghulis    schedule 21.06.2016    source источник
comment
Вы смотрели на SKMutableTexturemodifyPixelDataWithBlock? По-видимому, вы можете изменить данные пикселей на текстуре. Если у вас есть SKSpriteNode с текстурой, вы сможете изменять ее попиксельно. Для получения значений цвета пикселя кажется, что вам нужно использовать, например, UIView.   -  person OwlOCR    schedule 21.06.2016
comment
@GOR Я никогда не использовал modifyPixelDataWithBlock, можете ли вы дать какой-нибудь ответ, чтобы показать, как это сделать?   -  person Alessandro Ornano    schedule 21.06.2016
comment
@GOR Звучит выполнимо. Я прочитал документ, в нем говорится, что мне лучше не делать этого из-за производительности, если у меня нет выбора. Я не уверен, как он работает с большим количеством пикселей и часто обновляется. Тем не менее, можете ли вы показать мне некоторые коды для некоторых ссылок на учебники? Спасибо   -  person Valar Morghulis    schedule 21.06.2016
comment
Не использовал его. Поможет ли это? stackoverflow .com/questions/28398677/   -  person OwlOCR    schedule 22.06.2016


Ответы (1)


Недавно я попробовал это расширение, чтобы получить пиксель из SKTexture, и это сработало для меня:

extension SKTexture {
    func getPixelColorFromTexture(position: CGPoint) -> SKColor {
        let view = SKView(frame: CGRectMake(0, 0, 1, 1))
        let scene = SKScene(size: CGSize(width: 1, height: 1))
        let sprite  = SKSpriteNode(texture: self)
        sprite.anchorPoint = CGPointZero
        sprite.position = CGPoint(x: -floor(position.x), y: -floor(position.y))
        scene.anchorPoint = CGPointZero
        scene.addChild(sprite)
        view.presentScene(scene)
        var pixel: [UInt8] = [0, 0, 0, 0]
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue).rawValue
        let context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, CGColorSpaceCreateDeviceRGB(), bitmapInfo)
        UIGraphicsPushContext(context!)
        view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
        UIGraphicsPopContext()
        return SKColor(red: CGFloat(pixel[0]) / 255.0, green: CGFloat(pixel[1]) / 255.0, blue: CGFloat(pixel[2]) / 255.0, alpha: CGFloat(pixel[3]) / 255.0)
    }
}
person Alessandro Ornano    schedule 21.06.2016
comment
Я прошел через ваш ответ. Я считаю, что это работает, но у меня есть несколько опасений. (1): Каждый раз, когда он считывает один пиксель, он создает новый SKView, новый SKScene, новый Sprite. Поскольку я имею дело со многими пикселями для каждого кадра обновления (60 кадров в секунду), я могу представить, что это приведет к плохой производительности. Как я упоминал в своем посте, я попытался создать UIView для каждого пикселя, затем получить цвет и изменить цвет, а также обновить каждый кадр. - person Valar Morghulis; 21.06.2016
comment
(2): В данный момент я не имею дела с SKTexture. Все, что у меня есть, это чистый цветной фон с каким-то спрайтом чистого цвета. Я думаю, что могу преобразовать их в текстуры, но я хочу знать, смогу ли я сначала напрямую работать с Core Graphics. - person Valar Morghulis; 21.06.2016
comment
Мой метод следует реализации Sprite-kit в UIKit, поэтому нам нужно представить сцену для работы с CGBitmapContextCreate (ширина и высота равны 1). Я пробовал, и, кажется, не мешает fps. Если вы попробуете другой способ, и он сработает, пожалуйста, напишите об этом, может быть, это поможет всем. Мне нравится ваш вопрос, за него проголосовали бы или присудили, это очень интересно. - person Alessandro Ornano; 21.06.2016
comment
Метод получения цвета не сильно повлияет на fps. Меня беспокоит установка шага цвета. Я ищу более фундаментальный метод, например: (1) вычислить все пиксели, которые необходимо изменить, (2) обновить все цвета в методе обновления одного кадра. Я пытался сделать это в UIView, но каждый раз, когда я меняю цвета пикселей, рамка автоматически обновляется. Так что производительность действительно плохая. Я считаю, что реализация более низкого уровня, такая как CoreGraphics, справится с этой задачей, но я не знаком с этим. Я найду способ и опубликую ответ здесь, если это возможно. - person Valar Morghulis; 21.06.2016
comment
Я рад, что тебе это тоже интересно. Этот вопрос навеян некоторыми играми, похожими на песок. Здесь вы можете найти один вопрос, который я задавал ранее. здесь. Судя по ответу, кажется, что это можно сделать для JS очень легко. Я искал аналогичную реализацию для Swift. Скажите мне, если вы найдете какое-либо хорошее решение в будущем. - person Valar Morghulis; 21.06.2016
comment
Да, хорошие наблюдения. Я здесь, потому что, честно говоря, SKShapeNode — кусок дерьма! Слишком много форм, чтобы простые динамические объекты тратили мою производительность в секунду, поэтому изменение цвета пикселей кажется единственным способом сделать это. Я думал о расширении, которое имеет массив пикселей в качестве входных данных (то есть 1 пиксель или n пикселей). Я попытаюсь изучить метод, надеюсь, у кого-то есть отличное решение, я опубликую свои эксперименты здесь. - person Alessandro Ornano; 21.06.2016
comment
ХА-ХА, больше не могу с тобой согласиться насчет ДЕРЬМОВОГО SKShapeNode. Я прочитал много статей о том, насколько дерьмовым является ShapeNode, прежде чем я начал делать какие-либо игры. Я не обращал внимания, пока не использую некоторые в своей игре. Это действительно разрушает производительность, поскольку будет перерисовывать себя в КАЖДОМ кадре! Таким образом, обходной путь для меня - создать shapeNode, затем сохранить его как sktexture, а затем использовать его для создания SKSpriteNode, и это работает как шарм. Может быть, вы можете попробовать это, если не имеете дело с пикселями. Но с пикселем мне нужно найти другой метод. - person Valar Morghulis; 21.06.2016
comment
Кстати, я нашел много статей о том, как получить/установить пиксель для UIImage, так как есть приложения, имеющие дело с фильтрами/редактированием фотографий и т. д. Но нет статей о том, как напрямую изменить пиксель в UIView или SKScene, я бы изобразил его должно быть возможно, используя те же методы в UIImage. Я бы посмотрел в этом направлении. - person Valar Morghulis; 21.06.2016
comment
Да, в Sprite-kit нет статей о пикселях как для объектива-с, так и для свифта. Когда вы воссоздаете ShapeNode, вы создаете подкласс SKNode? На самом деле я борюсь с этими динамическими линиями, составленными из глупых связанных точек SKShapeNode, удаленных и всегда воссоздаваемых заново для более больших линий с помощью cgpath. - person Alessandro Ornano; 21.06.2016
comment
Давайте продолжим обсуждение в чате. - person Alessandro Ornano; 21.06.2016