Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SpriteKit starter, draw grid, detect touches on sprites, cause neighboring sprites to react
import Foundation
import SpriteKit
class Box {
let sprite: SKShapeNode
let cellAddress: XYPair
var position: CGPoint {
get { return sprite.position }
set { sprite.position = newValue }
}
init(position: CGPoint, cellAddress: XYPair, dimensions: CGSize) {
self.cellAddress = cellAddress
self.sprite = SKShapeNode(rectOf: dimensions)
self.sprite.position = position
self.sprite.strokeColor = .black
let label = SKLabelNode(text: "Click me!")
label.fontColor = .black
label.fontName = "Courier New"
label.fontSize = 16.0 * (10.0 / CGFloat(max(gridWidth, gridHeight)))
self.sprite.addChild(label)
}
func addToScene(_ scene: SKScene) {
scene.addChild(self.sprite)
}
func beFancy() {
sprite.alpha = 0
sprite.fillColor = getRandomColor()
sprite.children[0].alpha = 0
let direction: CGFloat = Bool.random() ? 2.0 : -2.0
let rotate = SKAction.rotate(byAngle: direction * CGFloat.pi, duration: 0.5)
let fade = SKAction.fadeAlpha(to: 1.0, duration: 0.5)
sprite.run(SKAction.group([rotate, fade])) { self.sprite.children[0].alpha = 1 }
}
}
import Foundation
import SpriteKit
// Change these to see different grid sizes
let gridWidth = 10
let gridHeight = 10
class CellGrid {
let boxes: [[Box]]
init(_ scene: SKScene) {
let boxWidth = scene.size.width / CGFloat(gridWidth)
let boxHeight = scene.size.height / CGFloat(gridHeight)
let boxDimensions = CGSize(width: boxWidth, height: boxHeight)
let b: [[Box]] = (0..<gridWidth).map { gridX in
let sceneX = (CGFloat(gridX) + 0.5) * boxWidth
return (0..<gridHeight).map { gridY in
let sceneY = (CGFloat(gridY) + 0.5) * boxHeight
return Box(
position: CGPoint(x: sceneX, y: sceneY),
cellAddress: XYPair(gridX, gridY),
dimensions: boxDimensions
)
}
}
self.boxes = b
self.boxes.joined().forEach { box in
box.sprite.userData = ["Box" : box]
scene.addChild(box.sprite)
}
}
subscript(_ x: Int, _ y: Int) -> Box { return self.boxes[x][y] }
subscript(_ cellAddress: XYPair) -> Box { return self.boxes[cellAddress.x][cellAddress.y] }
}
import AppKit
import Foundation
func getColorName(_ color: NSColor) -> String {
switch color {
case .black: return "black"
case .blue: return "blue"
case .brown: return "brown"
case .white: return "white"
case .darkGray: return "darkGray"
case .lightGray: return "lightGray"
case .orange: return "orange"
case .purple: return "purple"
case .gray: return "gray"
case .red: return "red"
case .green: return "green"
case .blue: return "blue"
case .cyan: return "cyan"
case .magenta: return "magenta"
case .yellow: return "yellow"
default: return String(describing: color)
}
}
func getRandomColor() -> NSColor {
return [
NSColor.black, NSColor.white, NSColor.gray, NSColor.red, NSColor.green,
NSColor.blue, NSColor.cyan, NSColor.magenta, NSColor.yellow, NSColor.brown,
NSColor.darkGray, NSColor.lightGray, NSColor.orange, NSColor.purple
].randomElement()!
}
import SpriteKit
import GameplayKit
struct XYPair {
let x: Int
let y: Int
init(_ x: Int, _ y: Int) { self.x = x; self.y = y }
static func + (_ lhs: XYPair, _ rhs: XYPair) -> XYPair {
return XYPair(lhs.x + rhs.x, lhs.y + rhs.y)
}
}
class GameScene: SKScene {
var cellGrid: CellGrid!
private func box(at position: CGPoint) -> Box? {
var someNode = nodes(at: position).first
if someNode is SKLabelNode { someNode = someNode!.parent }
guard let theSprite = someNode as? SKShapeNode else { return nil }
guard let theBox = theSprite.userData?["Box"] as? Box else { return nil }
return theBox
}
override func didMove(to view: SKView) {
self.anchorPoint = CGPoint(x: 0.0, y: 0.0)
self.backgroundColor = .white
cellGrid = CellGrid(self)
}
override func mouseUp(with event: NSEvent) {
self.touchUp(atPoint: event.location(in: self))
}
func secondaryTouch(from primaryTouch: Box) {
let neighborOffsets = [
XYPair(+0, +1), // North
XYPair(+1, +1), // Northeast
XYPair(+1, +0), // East
XYPair(+1, -1), // Southeast
XYPair(+0, -1), // South
XYPair(-1, -1), // Southwest
XYPair(-1, +0), // West
XYPair(-1, +1), // Northwest
]
neighborOffsets.forEach {
let neighborCellAddress = primaryTouch.cellAddress + $0
if neighborCellAddress.x < 0 || neighborCellAddress.x >= gridWidth ||
neighborCellAddress.y < 0 || neighborCellAddress.y >= gridHeight {
return
}
let neighborBox = cellGrid[neighborCellAddress]
neighborBox.beFancy()
}
}
func touchUp(atPoint pos : CGPoint) {
guard let clickedBox = box(at: pos) else { return }
clickedBox.sprite.fillColor = .blue
clickedBox.sprite.blendMode = .replace
secondaryTouch(from: clickedBox)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment