G'Day,
I have a problem that has appeared in a game I wrote for my kids. After some investigation I have "discovered" the following issue:
In the original game sprite are loaded via
let sprite = SKSpriteNode(texture: atlas!.textureNamed("something")
The texture atlas used has a large number of small textures, "images" in it. This results in a working and happy game on the older devices , iPhone 7, iPad Air, iPad Pro 12.9 inch. However on the iPhone X etc., and on the iPhone X simulator any of the images loaded from the atlas are displayed either as tiny little dots or not at all. There are no compiler errors and no runtime errors. I am assuming this is something to do with screen resolution, but what? If I load the images via an init(imageNamed: "something") call the self same images are correctly scaled and displayed. I have created a small stand alone program that illustrates this issue, code below: I also included two screen grabs showing the self same code loaded and running on an iPad and an iPhone Xsmax. The iPad image shows two platforms and the bunnies whilst the iPhone image shows them missing.
The two atlas files contain the platform and GEM and bunny images, the first atlas also contains about 90 small images in total. As you can see the first atlas images are incorrectly loaded, however if I reduce the number of images contained below about 30 images it all works. Oh and the compiler is not complaining or splitting the atlas files up either. So I suppose the final question is in two parts:
1 What is actually happening?
2 How to fix it?
The code is as follows:
//
// GameScene.swift
// SpriteTest
//
//
import SpriteKit
class GameScene: SKScene {
let player = SKSpriteNode(imageNamed: "player")
var atlas :SKTextureAtlas?
var atlas2 :SKTextureAtlas?
var tile : SKNode?
var tile2 : SKNode?
override func didMove(to view: SKView) {
// White background for visibility
backgroundColor = SKColor.white
player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
addChild(player)
// first platform "does not appear on iPhone X"
atlas = SKTextureAtlas(named: "Tiles")
tile = SKSpriteNode(texture: atlas!.textureNamed("platform"))
tile?.zPosition = 50
tile?.physicsBody?.isDynamic = true
tile?.physicsBody?.affectedByGravity = false
tile?.position = CGPoint(x: size.width * 0.1, y : size.height * 0.2)
addChild(tile!)
atlas2 = SKTextureAtlas(named: "Smallatlas")
// Second platform always appears
tile2 = SKSpriteNode(texture: atlas2!.textureNamed("platform"))
tile2?.zPosition = 50
tile2?.physicsBody?.isDynamic = true
tile2?.physicsBody?.affectedByGravity = false
tile2?.position = CGPoint(x: size.width * 0.6, y : size.height * 0.2)
addChild(tile2!)
run(SKAction.repeatForever(
SKAction.sequence([
SKAction.run(addMonster),
SKAction.wait(forDuration: 1.0)
])
))
}
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
func addMonster() {
// First monster "bunny" does not appear on iPhone X
let monster = SKSpriteNode(texture: atlas!.textureNamed("chocolate-bunny150"))
// Determine where to spawn the monster along the Y axis
let actualY = random(min: monster.size.height/2, max: size.height - monster.size.height/2)
// Position the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)
// Add the monster to the scene
addChild(monster)
// Determine speed of the monster
let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
// Create the actions
let actionMove = SKAction.move(to: CGPoint(x: -monster.size.width/2, y: actualY),
duration: TimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
monster.run(SKAction.sequence([actionMove, actionMoveDone]))
addMonster2()
}
func addMonster2() {
// Second monster always appears
let monster2 = SKSpriteNode(texture: atlas2!.textureNamed("gem"))
// Determine where to spawn the monster along the Y axis
let actualY = random(min: monster2.size.height/2, max: size.height - monster2.size.height/2)
// Position the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster2.position = CGPoint(x: size.width + monster2.size.width/2, y: actualY)
// Add the monster to the scene
addChild(monster2)
// Determine speed of the monster
let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
// Create the actions
let actionMove = SKAction.move(to: CGPoint(x: -monster2.size.width/2, y: actualY),
duration: TimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
monster2.run(SKAction.sequence([actionMove, actionMoveDone]))
}
}
User contributions licensed under CC BY-SA 3.0