Should I use a TileMap node for a puzzle game?

For the grid in a match-3 puzzle game, would you recommend a TileMap node or simple sprite nodes positioned one by one? A TileMap is good for a static background, but if I need to move the tiles, will it work?


I'm asking because I have a weird bug where a gap will randomly appear between some tiles. I use simple SKSpriteNodes that are positioned side by side. Some of the tiles have a tiny gap of maybe 1 pixel between them. But not always. It appears to be random. Maybe I have a bug with the position of the tiles. So I wonder if it would be simpler with a TileMap.

Accepted Reply

This question is more about removing pixel gaps.

In general, the strategy to remove pixel gaps is to ensure your textures are pixel aligned with the SKView's backing store. There are few properties to check to ensure this: node position, sprite anchorPoint, node scale, camera scale. These kinds of properties must be pixel aligned manually because SpriteKit does not offer a facility to do it on your behalf. A typical technique is to round irrational values to the base 2 number system such as with the following function:


    static func round_pow_2( _ value: CGFloat, decimalPlaces: CGFloat ) -> CGFloat {
        let decimalValue = pow( 2.0, decimalPlaces )
        if decimalValue == 0.0 { return value }
        return CoreGraphics.round( value * decimalValue ) / decimalValue
    }


Keeping in mind that on retina screens, you are allowed at least one base-2 decimal digit of precision to account for the fact that each screen point is at least 2 pixels wide. The actual ratio of screen points to pixels in a SpriteKit game is defined by SKView.contentScaleFactor.


It is also important to ensure that normal texture coordinates are pixel aligned when creating textures with sub rects using:

SKTexture( rect: normalRect, in: sourceTexture )


Regarding SKTileMapNode for use with small grids: this class is mostly a time saver when using Xcode's SpriteKit editor to design large maps (especially, those that make use of terrain `automapping`). With a board game of such few tiles, it doesn't sound like SKTileMapNode saves much time as compared to its restrictions (e.g., SKTimeMapNode tiles are not nodes, so it does not inherently support actions, physics bodies, touch handling, etc.).

Replies

This question is more about removing pixel gaps.

In general, the strategy to remove pixel gaps is to ensure your textures are pixel aligned with the SKView's backing store. There are few properties to check to ensure this: node position, sprite anchorPoint, node scale, camera scale. These kinds of properties must be pixel aligned manually because SpriteKit does not offer a facility to do it on your behalf. A typical technique is to round irrational values to the base 2 number system such as with the following function:


    static func round_pow_2( _ value: CGFloat, decimalPlaces: CGFloat ) -> CGFloat {
        let decimalValue = pow( 2.0, decimalPlaces )
        if decimalValue == 0.0 { return value }
        return CoreGraphics.round( value * decimalValue ) / decimalValue
    }


Keeping in mind that on retina screens, you are allowed at least one base-2 decimal digit of precision to account for the fact that each screen point is at least 2 pixels wide. The actual ratio of screen points to pixels in a SpriteKit game is defined by SKView.contentScaleFactor.


It is also important to ensure that normal texture coordinates are pixel aligned when creating textures with sub rects using:

SKTexture( rect: normalRect, in: sourceTexture )


Regarding SKTileMapNode for use with small grids: this class is mostly a time saver when using Xcode's SpriteKit editor to design large maps (especially, those that make use of terrain `automapping`). With a board game of such few tiles, it doesn't sound like SKTileMapNode saves much time as compared to its restrictions (e.g., SKTimeMapNode tiles are not nodes, so it does not inherently support actions, physics bodies, touch handling, etc.).

Thank you very much for your answer.


You are right, the question is about a gap problem. I just thought maybe a TileMap would help with this problem.


I'm a little ashaned to ask how you would call this function to fix this problem. I made some test and it didn't change anything. I find it weird that we have to work with points but then we need to tweak the code to deal with the real pixel value.

Found it!


I thought my sprite nodes were already all aligned on pixels because their x-y values were all rounded to Int. But the parent SKNode was not aligned on a pixel. It was at x=0.0, y=4.25. If I round it to y=4.0, all the gaps disapear!


Thanks again for you explanation. It headed me in the right direction.