Confused
Confused

Reputation: 6278

SpriteKit texture "scaling" different from one to another

Exact same texture, different results

Here an SKSpriteNode and SKShapeNode are given the same texture, from a texture atlas.

The SKSpriteNode is on the right, and it does the right thing.

enter image description here

The SKShapeNode is on the left, and doing the wrong thing.

Please, what am I doing wrong?

here's the code...

override func didMove(to view: SKView) {


    let myTextureAtlas = SKTextureAtlas(named: "demoArt")
    let arrayOfFileNames = myTextureAtlas.textureNames
    let myTexture = myTextureAtlas.textureNamed(arrayOfFileNames.last!)

    let circleShape = SKShapeNode(circleOfRadius: 180)
    circleShape.fillColor = SKColor.white
    circleShape.fillTexture = myTexture
    circleShape.position = CGPoint(x: 256, y: 384)
    addChild(circleShape)

    let circleSprite = SKSpriteNode(color: SKColor.white, size: CGSize(width: 320, height: 320))
    circleSprite.texture = myTexture
    circleSprite.position = (CGPoint(x: 768, y: 384))
    addChild(circleSprite)

    print(myTexture)

The result of print(myTexture) is correct:

<SKTexture> 'seven.png' (512 x 512)

If you want to test this out, here are the image files going into the "atlas"...

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

Upvotes: 2

Views: 427

Answers (2)

Alessandro Ornano
Alessandro Ornano

Reputation: 35392

This is not a bug (it was wanted as is) , SKShapeNode scales a fill texture by default, instead of repeating the pattern and you don't have a direct control on this scaling.

As explained to the API reference:

Shape nodes are useful for content that cannot be easily decomposed into simple textured sprites. Shape nodes are also very useful for building and displaying debugging information on top of your game content. However, the SKSpriteNode class offers higher performance than this class, so use shape nodes sparingly.

Using SKShapeNode beyond from these dictates will needlessly cost performance and can produce visual defects.

Upvotes: 0

Zion
Zion

Reputation: 1566

I implemented your code and used a different set of textures (letters instead of numbers) and I got the exact same behavior. I suspect that SKShapeNode implements its fillTexture differently than SKSpriteNode.

In my code below, I made four nodes. The top two circles are SKShapeNodes and the bottom two are SKSpriteNodes.

  • top left SKShapeNode uses SKTexture(imageNamed: "a.png")
  • top right SKShapeNode uses myTexture
  • bottom left SKSpriteNode uses myTexture
  • bottom right SKSpriteNode uses SKTexture(imageNamed: "a.png")

To work around your issue, instead of using the texture atlas, just use an individual SKTexture like the top left circle in my example.

Here is my GameScene.swift file:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    override func didMove(to view: SKView) {

        let myTextureAtlas = SKTextureAtlas(named: "8bitfont")
        let arrayOfFileNames = myTextureAtlas.textureNames
        print(arrayOfFileNames)
        let myTexture = myTextureAtlas.textureNamed("a.png")

        // Top left circle
        let circleShape1 = SKShapeNode(circleOfRadius: 160)
        circleShape1.fillColor = SKColor.white
        circleShape1.fillTexture = SKTexture(imageNamed: "a.png")
        circleShape1.position = CGPoint(x: -180, y: 180)
        addChild(circleShape1)

        // Top right circle
        let circleShape2 = SKShapeNode(circleOfRadius: 160)
        circleShape2.fillColor = SKColor.white
        circleShape2.fillTexture = myTexture as SKTexture
        circleShape2.position = CGPoint(x: 180, y: 180)
        addChild(circleShape2)

        // Bottom left circle
        let circleSprite1 = SKSpriteNode(color: SKColor.white, size: CGSize(width: 320, height: 320))
        circleSprite1.texture = myTexture
        circleSprite1.position = (CGPoint(x: -180, y: -180))
        addChild(circleSprite1)

        // Bottom right circle
        let circleSprite2 = SKSpriteNode(color: SKColor.white, size: CGSize(width: 320, height: 320))
        circleSprite2.texture = SKTexture(imageNamed: "a.png")
        circleSprite2.position = (CGPoint(x: 180, y: -180))
        addChild(circleSprite2)

        print(myTexture)
    }
}

Here is the result I get:

Result

Here is the full project on github:

https://github.com/starkindustries/SKShapeNodeVsSKSpriteNode

Upvotes: 2

Related Questions