Hi,
I've been playing about with Spritekit recently and have come across a somewhat novel issue. I've created a scene with three sprites, and can move them about happily. I then save, reset and reload, and that's where the funkiness starts - there is nothing amiss with the saving and loading functions, and everything else appears to be working well. I hope the following screenshots and explanation outline well enough what I'm talking about.
1) I generate three objects and their position is set at 0.0...

2) I move them to the following positions...

3) I then save and reload, there is an almost imperceptible shifting of the sprites...

4) I then move the top sprite back to the middle of the screen...

5) I then save and reload...and it jumps down to the bottom of the screen..!

If I save and load without moving any of the sprites they stay in the same position.
Here is the code that I'm using:
import Foundation
import SpriteKit
class SpriteKitManager: ObservableObject {
static let shared = SpriteKitManager()
// Create a scene with a default size
let scene = GameScene(size: CGSize(width: 640, height: 480))
init(){
// Set the scale mode to resize fill
scene.scaleMode = .resizeFill
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
}
}
class GameScene: SKScene {
override func didMove(to view: SKView) {
refreshAnimalSprites()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
func refreshAnimalSprites(){
for child in children {
child.removeFromParent()
}
for animal in animalManager.animals {
let animalSprite = AnimalSprite(id: animal.id, animalType: animal.type)
animalSprite.position = animal.position
addChild(animalSprite)
}
}
}
class AnimalSprite : SKNode {
var id : Int
private var currentNode: SKNode?
override var isUserInteractionEnabled: Bool {
set {
// ignore
}
get {
return true
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let touchedNodes = self.nodes(at: location)
for node in touchedNodes.reversed() {
self.currentNode = node
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first, let node = self.currentNode {
let touchLocation = touch.location(in: self)
// Convert the touch location to the coordinate system of the parent node
let nodeLocation = self.convert(touchLocation, to: node.parent!)
node.position = nodeLocation
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if self.currentNode != nil {
if let animal = animalManager.animals.first(where: { $0.id == id }) {
if let touch = touches.first, let node = self.currentNode {
let touchLocation = touch.location(in: self)
// Convert the touch location to the coordinate system of the parent node
let nodeLocation = self.convert(touchLocation, to: node.parent!)
animal.position = nodeLocation
}
}
self.currentNode = nil
}
}
init(id: Int, animalType: AnimalType){
var sprite : SKNode
switch(animalType) {
case .dog:
sprite = SKSpriteNode(imageNamed: "Dog" )
case .cat:
sprite = SKSpriteNode(imageNamed: "Cat" )
case .owl:
sprite = SKSpriteNode(imageNamed: "Owl" )
case .penguin:
sprite = SKSpriteNode(imageNamed: "Penguin" )
case .human:
sprite = SKSpriteNode(imageNamed: "Person" )
default:
sprite = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
}
self.id = id
super.init()
addChild(sprite)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I am confident with the rest of the code, I just can't track down what I am getting wrong with my positioning. There is no scaling going on beyond the resizeFill. Whenever I move a sprite and save/reload it's almost like there's a move along the same vector, if that makes sense, and then it stays where it is.
If anyone could shed any light, I'd be grateful.
Many thanks,
Jes