Best Class File Organization Practice?

Hello! I am quite new to swift development, I've been making games in Lua for the last 8 years and this is my first real venture into a new language.


Right now I'm trying to create a simple Snake game to get familiar with the SpriteKit framework. When using Lua I would place each "class" into it's own file, for example with this game I would have a snake.lua that holds all of the snakes data and functions. I am sure that is a common practice with Swift as well but I'm having trouble figuring out exactly how to use it with SpriteKit. All of the SpriteKit examples I find contain all of their code in one file because their project is so small.


What's the best way to setup a file like Snake.swift? Not the actual functionality of the snake but just the best practice for setting up a class like that to use with spritekit. Right now I have

func loadSnake() {
    let snake=SKSpriteNode(imageNamed: "Spaceship")
}

inside of snake.swift, and then I am executing loadSnake() inside of didMove() in GameScene.swift. The big problem that I ran into is that I can't add the snake to the scene because I can't access self.addChild(). I'm sure this isn't even close to what I should be doing but hopefully that gives an idea of what I am trying to accomplish.


TL;DR What's the best way to put a class (like Snake in a snake game) in it's own file?


Sorry I'm super new right now this is probably a super simple question but I'm having trouble finding information on this topic. Thank you in advanced!

Accepted Reply

Hiya and welcome 🙂!


What you're describing is basic object-oriented programming, where repeated and logically separate functionalities are separated into individual objects, or classes. OOP is very much part of Swift, as it was also with Obj-C. It's also always a great idea to ask for best practices, so no worries.


Here's an example of a Snake class initiated in GameScene:


GameScene.swift

import SpriteKit


class GameScene: SKScene {
  
    override func didMove(to view: SKView) {
        setupSnake()
    }
  
    func setupSnake() {
        let snake = Snake(snakeSomeProperty: 5)
        addChild(snake)
    }
}


Snake.swift

import SpriteKit


class Snake: SKNode {
   
    var someProperty: Int!
   
    convenience init(snakeSomeProperty: Int) {
        self.init()
       
        someProperty = snakeSomeProperty
       
        setup()
    }
   
    override init() {
        super.init()
    }
   
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
   
    func setup() {
        let image = SKSpriteNode(imageNamed: "Spaceship")
        addChild(image)
    }
}


GameScene runs an optional setup class for all things snake. A variable is passed as a property for snake, if you let's say wanted to feed the snake a length, or something. Snake itself has a convenience initializer that assigns its own property with the variable passed in. It then runs an optional setup function to actually build the snake from images or whatever. Snake is a sub-class of SKNode (which is usual), but it could be something else as well, such as SKSpriteNode.

Replies

Hiya and welcome 🙂!


What you're describing is basic object-oriented programming, where repeated and logically separate functionalities are separated into individual objects, or classes. OOP is very much part of Swift, as it was also with Obj-C. It's also always a great idea to ask for best practices, so no worries.


Here's an example of a Snake class initiated in GameScene:


GameScene.swift

import SpriteKit


class GameScene: SKScene {
  
    override func didMove(to view: SKView) {
        setupSnake()
    }
  
    func setupSnake() {
        let snake = Snake(snakeSomeProperty: 5)
        addChild(snake)
    }
}


Snake.swift

import SpriteKit


class Snake: SKNode {
   
    var someProperty: Int!
   
    convenience init(snakeSomeProperty: Int) {
        self.init()
       
        someProperty = snakeSomeProperty
       
        setup()
    }
   
    override init() {
        super.init()
    }
   
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
   
    func setup() {
        let image = SKSpriteNode(imageNamed: "Spaceship")
        addChild(image)
    }
}


GameScene runs an optional setup class for all things snake. A variable is passed as a property for snake, if you let's say wanted to feed the snake a length, or something. Snake itself has a convenience initializer that assigns its own property with the variable passed in. It then runs an optional setup function to actually build the snake from images or whatever. Snake is a sub-class of SKNode (which is usual), but it could be something else as well, such as SKSpriteNode.

Thank you so much! Works perfect, this is exactly what I was trying to figure out.

No problemo 😀! Stick around on the forums.