I have an assignment where I need to create a game with SpriteKit. It should have a button moving randomly within a view and if I click on it I get points. The issue is that I have no idea how to create a button in SpriteKit.
Do I need to do a workaround by using a SKSpriteNode? But how would I make it look like a standard button? Or can I actually create a button somehow for that?
CodePudding user response:
SpriteKit has no built-in SKButton
class. but we can build some basic functionality. as sangony said you need three parts: draw the graphics (I'm using SKShapeNode
for simplicity but you could use SKSpriteNode
); move the node; add picking functionality. here is some code to illustrate.
Draw
add a SKShapeNode
or SKSpriteNode
to your SKNode class
shape = SKShapeNode(circleOfRadius: 40)
shape.fillColor = .green
addChild(shape)
Move
SKAction
is very useful. here is an example that moves to a random position, then recursively calls itself. stop/go is regulated by a boolean flag.
func movement() {
print("movement")
let DURATION:CGFloat = 2.0
let random_x = CGFloat.random(in: -200...200)
let random_y = CGFloat.random(in: -200...200)
let random_point = CGPoint(x: random_x, y: random_y)
let move = SKAction.move(to: random_point, duration: DURATION)
move.timingMode = .easeInEaseOut
let wait = SKAction.wait(forDuration: DURATION)
let parallel = SKAction.group([move,wait])
let recursion = SKAction.run {
if self.isInMotion { self.movement() }
}
let serial = SKAction.sequence([parallel, recursion])
self.run(serial)
}
Pick
Testing for user clicks in a scene is called picking. I use a PickableNode
protocol which helps filter out which SKNodes
you want to be clickable.
extension GameScene {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
//call `pick` on any `PickableNode` that exists at touch location
let location = touch.location(in: self)
let _ = self.nodes(at: location).map { ($0 as? PickableNode)?.pick() }
}
}
}
Here is the whole completed class
protocol PickableNode {
func pick()
}
class Button: SKNode, PickableNode {
let shape:SKShapeNode
var isInMotion:Bool = true
override init() {
shape = SKShapeNode(circleOfRadius: 40)
shape.fillColor = .green
super.init()
addChild(shape)
movement()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func movement() {
print("movement")
let DURATION:CGFloat = 2.0
let random_x = CGFloat.random(in: -200...200)
let random_y = CGFloat.random(in: -200...200)
let random_point = CGPoint(x: random_x, y: random_y)
let move = SKAction.move(to: random_point, duration: DURATION)
move.timingMode = .easeInEaseOut
let wait = SKAction.wait(forDuration: DURATION)
let parallel = SKAction.group([move,wait])
let recursion = SKAction.run {
if self.isInMotion { self.movement() }
}
let serial = SKAction.sequence([parallel, recursion])
self.run(serial)
}
func pick() {
print("i got picked")
if !isInMotion {
isInMotion = true
shape.fillColor = .green
movement()
} else {
isInMotion = false
shape.fillColor = .red
self.removeAllActions()
}
}
}