Reputation: 6278
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.
The SKShapeNode
is on the left, and doing the wrong thing.
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"...
Upvotes: 2
Views: 427
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
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.
SKTexture(imageNamed: "a.png")
myTexture
myTexture
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:
Here is the full project on github:
https://github.com/starkindustries/SKShapeNodeVsSKSpriteNode
Upvotes: 2