swiftsprite-kitcore-imagesktilemapnode

Programmatically creating an SKTileDefinition


I've been beating my head against a wall for hours now. I am trying to modify a texture inside my app using a CIFilter and then use that new texture as a part of a new SKTileDefinition to recolor tiles on my map. The function bellow finds tiles that players "own" and attempts to recolor them by changing the SKTileDefinition to the coloredDefinition.

  func updateMapTileColoration(for players: Array<Player>){
    for player in players {
        for row in 0..<mainBoardMap!.numberOfRows {
            for col in 0..<mainBoardMap!.numberOfColumns {
                let rowReal = mainBoardMap!.numberOfRows - 1 - row
                if player.crownLocations!.contains(CGPoint(x: row, y: col)) {
                    if let tile = mainBoardMap!.tileDefinition(atColumn: col, row: rowReal) {
                        let coloredDefinition = colorizeTile(tile: tile, into: player.color!)
                        print(coloredDefinition.name)
                        mainBoardMap!.tileSet.tileGroups[4].rules[0].tileDefinitions.append(coloredDefinition)
                        mainBoardMap!.setTileGroup(crownGroup!, andTileDefinition: crownGroup!.rules[0].tileDefinitions[1], forColumn: col, row: rowReal)
                    }
                }
            }
        }
    }

And here is the function that actulaly applies the CIFilter: colorizeTile

func colorizeTile(tile: SKTileDefinition, into color: UIColor) -> SKTileDefinition{
        let texture = tile.textures[0]

        let colorationFilter = CIFilter(name: "CIColorMonochrome")
        colorationFilter!.setValue(CIImage(cgImage: texture.cgImage()), forKey: kCIInputImageKey)
        colorationFilter!.setValue(CIColor(cgColor: color.cgColor), forKey: "inputColor")
        colorationFilter!.setValue(0.25, forKey: "inputIntensity")
        let coloredTexture = texture.applying(colorationFilter!)

        let newDefinition = SKTileDefinition(texture: texture)
        newDefinition.textures[0] = coloredTexture
        newDefinition.name = "meow"

        return newDefinition
    }

I would love any help in figuring out why I cannot change the tileDefinition like I am trying to do. It seems intuitively correct to be able to define a new TileDefinition and add it to the tileGroup and then set the tile group to the specific tile definition. However, this is leading to blank tiles...

Any pointers?


Solution

  • After trying a bunch of things I finally figured out what is wrong. The tile definition wasn't being created correctly because I never actually drew a new texture. As I learned, a CIImage is not the drawn texture its just a recipe and we need a context to draw the texture. After this change, the SKTileDefinition is properly created. The problem wasn't where I thought it was so I am sort-of second hand anwering the question. My method for creating a SKTileDefinition was correct.

       if drawContext == nil{
            drawContext = CIContext()
        }
    
        let texture = tile.textures[0]
    
        let colorationFilter = CIFilter(name: "CIColorMonochrome")
        colorationFilter!.setValue(CIImage(cgImage: texture.cgImage()), forKey: kCIInputImageKey)
        colorationFilter!.setValue(CIColor(cgColor: color.cgColor), forKey: "inputColor")
        colorationFilter!.setValue(0.75, forKey: "inputIntensity")
    
        let result = colorationFilter!.outputImage!
        let output = drawContext!.createCGImage(result, from: result.extent)
        let coloredTexture = SKTexture(cgImage: output!)
    
        let newDefinition = SKTileDefinition(texture: texture)
        newDefinition.textures[0] = coloredTexture
        newDefinition.name = "meow"