I'm working on an app and I wrote a large part of an SKScene
in a single class. It works great, but when I took a (java) course this past semester, it seems that accepted industry practice is to separate it into many classes.
More specifically, my (SpriteKit) app contains a cat and a mouse and after finishing said course, I decide that instead of containing all their info in the SKScene
, I should separate some of it into multiple classes (a Player
superclass with Cat
and Mouse
subclasses) each containing their relevant info (such as x and y position,) and functions (such as moveCat
) with only Scene related functions and info in the Scene class.
The problem lies in the content of the functions.
Particularly one of the functions, pathBlocked
(which checks if there are any barriers blocking the desired path of movement) uses a lot of info that wouldn't make sense to contain inside the Player
object (such as all the info about the barriers on the board, and how much cheese was collected).
I can't just leave pathBlocked
as a Scene
function because there's a function that should belong to the cat (catAI
) which uses pathBlocked
to navigate. If it's a method of the scene, then it won't work. I'd need to instantiate a Scene object every time I wanted to call pathBlocked
.
Should I just forget about making the Cat
and Mouse
Classes or should I fill the Player
class with info that doesn't quite belong?
or is there a third option I'm not thinking of?
If you need a snippet of the code, I could include some of it.
Thanks!
Ok, so what you should do is
class Cat {
var sceneRef: GameScene? //or whatever scene is called
var xPos: CGFloat!
var yPos: CGFloat!
init(s: GameScene){//just example stuff
sceneRef = s
xPos = sceneRef!.childNodeWithName("cat").position.x
yPos = sceneRef!.childNodeWithName("cat").position.y //However, these variables will not stay up to date. If you need them current, you would have to do the same thing again, xPos = sceneRef!.childNode...etc.
}
func doStuff{
}
func createNewPath()
//create a new path
}
}
Then in the scene, you can do:
class GameScene: SKScene {
var cat: Cat?
override init(size: CGSize){
super.init(size: size)
cat = Cat(s: self)
func whatever() {
if (pathBlocked()){
cat!.createNewPath()
}
}
I think you will just have to unwrap it each time you use it, but XCode will tell you that.
^ credit for that should go to AMomchilov, I didn't know about weak references at all before this. It was a fun learning experience XD.
If you are looking to organize your code, another way you could do it is have an extension file for your scene, and throw all the low level function stuff in there, and keep all the high level stuff in the actual scene class. Make a new class, and call it SceneExtension or something:
import SpriteKit
//import whatever else you need
extension GameScene { //<- Or whatever your previous scene that you want to extend is called
func pathBlocked() {
//function code
}
//other functions
}
And just basically throw all the other functions that you don't want to look at and just take up space in the actual scene file. It acts like its in the same file, so you can call any of the functions in here, or use any variables from either class.