I'm trying to design my own DPad for my game but for some reason my onTouchesBegan() is not being called. I explored a bit and I think the reason for this is because my self.frame.size
is equal to (0,0)
for some reason even after I have added my child nodes (up, down, left, right nodes). I'm guessing since the size is 0, then there's nothing to detect a touch on. Is there something I'm doing that's glaringly wrong here? The only thing I can think of is maybe because the buttons are SKLabelNodes? But I have printed their sizes and they are all > 0.
protocol DPadDelegate {
func upTapped()
func downTapped()
func leftTapped()
func rightTapped()
}
open class DPad: SKNode {
private var buttonsSize: CGFloat
private var up: SKLabelNode!
private var down: SKLabelNode!
private var left: SKLabelNode!
private var right: SKLabelNode!
private var timer = Timer()
private var upHeld = false
private var downHeld = false
private var leftHeld = false
private var rightHeld = false
var delegate: DPadDelegate?
public lazy var width: CGFloat = {
return buttonsSize * 3
}()
public lazy var height: CGFloat = {
return buttonsSize * 3
}()
init(buttonsSize: CGFloat) {
self.buttonsSize = buttonsSize
super.init()
let center = SKLabelNode(text: "⏹")
up = SKLabelNode(text: "🔼")
down = SKLabelNode(text: "🔽")
left = SKLabelNode(text: "◀️")
right = SKLabelNode(text: "▶️")
center.fontSize = buttonsSize
up.fontSize = buttonsSize
down.fontSize = buttonsSize
left.fontSize = buttonsSize
right.fontSize = buttonsSize
center.position = CGPoint(x: 0, y: 0)
up.position = CGPoint(x: 0, y: buttonsSize)
down.position = CGPoint(x: 0, y: -buttonsSize)
left.position = CGPoint(x: -buttonsSize, y: 0)
right.position = CGPoint(x: buttonsSize, y: 0)
self.addChild(center)
self.addChild(up)
self.addChild(down)
self.addChild(left)
self.addChild(right)
print(self.frame.size)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("?")
if let touch = touches.first, up == atPoint(touch.location(in: self)) {
upTapped()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(upTapped), userInfo: nil, repeats: true)
}
if let touch = touches.first, down == atPoint(touch.location(in: self)) {
downTapped()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(downTapped), userInfo: nil, repeats: true)
}
if let touch = touches.first, left == atPoint(touch.location(in: self)) {
leftTapped()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(leftTapped), userInfo: nil, repeats: true)
}
if let touch = touches.first, right == atPoint(touch.location(in: self)) {
rightTapped()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(rightTapped), userInfo: nil, repeats: true)
}
}
open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
if upHeld && up != atPoint(location) {
timer.invalidate()
up.alpha = 1.0
upHeld = false
}
if downHeld && down != atPoint(location) {
timer.invalidate()
down.alpha = 1.0
downHeld = false
}
if rightHeld && right != atPoint(location) {
timer.invalidate()
right.alpha = 1.0
rightHeld = false
}
if leftHeld && left != atPoint(location) {
timer.invalidate()
left.alpha = 1.0
leftHeld = false
}
}
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
resetDPad()
}
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
resetDPad()
}
private func resetDPad() {
timer.invalidate()
up.alpha = 1.0
down.alpha = 1.0
left.alpha = 1.0
right.alpha = 1.0
upHeld = false
downHeld = false
rightHeld = false
leftHeld = false
}
@objc private func upTapped() {
upHeld = true
up.alpha = 0.6
delegate?.upTapped()
}
@objc private func downTapped() {
downHeld = true
down.alpha = 0.6
delegate?.downTapped()
}
@objc private func rightTapped() {
rightHeld = true
right.alpha = 0.6
delegate?.rightTapped()
}
@objc private func leftTapped() {
leftHeld = true
left.alpha = 0.6
delegate?.leftTapped()
}
}
add isUserInteractionEnabled = true
to your init func. Otherwise touches functions get ignored