Skip to content

Instantly share code, notes, and snippets.

@rjhoover
Created May 10, 2023 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rjhoover/063328fa1a727f3e647312652652c1a7 to your computer and use it in GitHub Desktop.
Save rjhoover/063328fa1a727f3e647312652652c1a7 to your computer and use it in GitHub Desktop.
import SpriteKit
struct Level {
enum CollisionTypes: UInt32 {
case player = 1
case wall = 2
case star = 4
case vortex = 8
case teleport = 16
case finish = 32
}
var levelLabel: SKLabelNode!
var levelFileName = "level1.txt"
var maxLevels = 9
var levelNodesArray = [SKSpriteNode]()
var level = 1 {
didSet {
levelLabel.text = "Level: \(level)"
levelFileName = "level\(level).txt"
}
}
var isLevelFinished = false
let wallImageName = "block"
let vortexImageName = "vortex"
let starImageName = "star"
let teleportImageName = "teleport"
let finishImageName = "finish"
let nextLevelLabelName = "nextLevel"
var teleportNodes: [String: SKSpriteNode?] = [:]
var teleportStartNode: SKSpriteNode!
var teleportEndNode: SKSpriteNode!
var startNodeKey = "teleportStart"
var endNodeKey = "teleportEnd"
var isSecondPass: Bool = false
let playerBallSize = 64
func loadLevelFile() -> [String] {
print("start loading level with \(levelFileName)")
guard let levelURL = Bundle.main.url(forResource: levelFileName, withExtension: nil) else {
fatalError("Could not find \(levelFileName) in the app bundle")
}
guard let levelString = try? String(contentsOf: levelURL) else {
fatalError("Failed to load \(levelFileName) from the app bundle")
}
return levelString.components(separatedBy: "\n")
}
mutating func displayLevel(_ lines: [String]) {
print("in displayLevel, level = \(level)")
for (row, line) in lines.reversed().enumerated() {
for (column, letter) in line.enumerated() {
let position = CGPoint(x: (playerBallSize * column) + (playerBallSize / 2), y: (playerBallSize * row) + (playerBallSize / 2))
switch letter {
case "x":
loadWall(at: position)
case "v":
loadVortex(at: position)
case "s":
loadStar(at: position)
case "t":
loadTeleport(at: position)
case "f":
loadFinish(at: position)
case " ":
let _ = "foo"
// nop
default:
fatalError("Unknown level symbol found: \(letter) at row \(row), col \(column) - Level file is invalid")
}
}
}
print("end displayLevel")
}
mutating func loadWall(at position: CGPoint) {
let node = SKSpriteNode(imageNamed: wallImageName)
node.name = wallImageName
node.position = position
node.zPosition = 0
node.physicsBody = SKPhysicsBody(rectangleOf: node.size)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = CollisionTypes.wall.rawValue
addChild(node)
levelNodesArray.insert(node, at: 0)
}
mutating func loadVortex(at position: CGPoint) {
let node = SKSpriteNode(imageNamed: vortexImageName)
node.name = vortexImageName
node.position = position
node.zPosition = 0
node.run(SKAction.repeatForever(SKAction.rotate(byAngle: .pi, duration: 1)))
node.physicsBody = SKPhysicsBody(circleOfRadius: node.size.width / 2)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = CollisionTypes.vortex.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.player.rawValue
node.physicsBody?.collisionBitMask = 0
addChild(node)
levelNodesArray.insert(node, at: 0)
}
mutating func loadStar(at position: CGPoint) {
let node = SKSpriteNode(imageNamed: starImageName)
node.name = starImageName
node.position = position
node.zPosition = 0
node.physicsBody = SKPhysicsBody(circleOfRadius: node.size.width / 2)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = CollisionTypes.star.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.player.rawValue
node.physicsBody?.collisionBitMask = 0
addChild(node)
levelNodesArray.insert(node, at: 0)
}
mutating func loadFinish(at position: CGPoint) {
let node = SKSpriteNode(imageNamed: finishImageName)
node.name = finishImageName
node.position = position
node.zPosition = 0
node.physicsBody = SKPhysicsBody(circleOfRadius: node.size.width / 2)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = CollisionTypes.finish.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.player.rawValue
node.physicsBody?.collisionBitMask = 0
addChild(node)
levelNodesArray.insert(node, at: 0)
}
mutating func loadTeleport(at position: CGPoint) {
let node = SKSpriteNode(imageNamed: teleportImageName)
node.name = teleportImageName // default name
node.position = position
node.zPosition = 0
let scaleDown = SKAction.scale(to: 0.7, duration: 0.75)
let scaleUp = SKAction.scale(to: 1.0, duration: 0.75)
let sequence = SKAction.sequence([scaleDown, scaleUp])
node.run(SKAction.repeatForever(sequence))
node.physicsBody = SKPhysicsBody(circleOfRadius: node.size.width / 2)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = CollisionTypes.teleport.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.player.rawValue
node.physicsBody?.collisionBitMask = 0
if teleportNodes[startNodeKey] != nil && isSecondPass {
node.name = endNodeKey
teleportNodes[endNodeKey] = node
addChild(node)
levelNodesArray.insert(node, at: 0)
} else {
print(" teleportNodes[startNodeKey] is nil or isSecondPass is false -- not end node scenario")
}
if teleportNodes[startNodeKey] == nil && isSecondPass == false {
node.name = startNodeKey
teleportNodes[startNodeKey] = node
isSecondPass = true
addChild(node)
levelNodesArray.insert(node, at: 0)
} else {
print(" start node already exists or isSecondPass is true - not start node scenario")
}
}
}
@rjhoover
Copy link
Author

In the methods:

  • loadWall
  • loadVortex
  • loadStar
  • loadFinish
  • loadTeleport

Each method creates a new SKSpriteNode, sets some properties for the node, then tries calls addNode() on the node.
I get a compile-time error on all the 'addChild()' of "Cannot find 'addChild' in scope"
I can't figure out why I'm getting the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment