My app has multiple balls, but only can be moved at a time. My code below shows that at touchesBegan I set specific fields used in touchesMoved. Within touchesCancelled and touchesEnded I reset everything.
This is my first Swift app, but not my first program, I know users like to try and crash apps. So with two fingers I started touching multiple balls as fast as I could, and eventually, yes, I ran through touchesBegan on another ball before the first one could be set as the "moving" ball. Is there any lag property where I can make the iOS wait even 0.3 seconds between touchesBegan?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let touchedNodes = self.nodes(at: location)
for node in touchedNodes{
if let theNode = node as? MyBall {
if theNode.nodeType == .ball, theNode.isMoving == false,
(myGV.currentBall == nil) {
theNode.isMoving = true
theNode.zPosition += 1
myGV.currentBall = theNode
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
guard touches.first != nil else { return }
if let touch = touches.first, let node = myGV.currentBall, node.isMoving == true {
let touchLocation = touch.location(in: self)
node.position = touchLocation
node.isMoving = true
node.inSlot = false
}
}
I think the natural thing is organize it around one individual active touch. In touchesMoved
, touchesEnded
, and touchesCancelled
, ignore everything when there's no active touch, and ignore any touches that are not the active touch. In touchesBegan
, ignore new touches if there's already an active touch. Finally, in touchesBegan
, if there's no active touch and the touch is on a ball, that touch becomes the active one and that ball becomes the being-moved ball. Sketch:
// activeTouch is a UITouch?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
if activeTouch == nil {
// Look for a touched ball; if found set that as the moving ball
// and set this touch as activeTouch
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
guard let active = activeTouch else { return }
for touch in touches {
if touch == active {
// Do stuff with the moving ball
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?){
guard let active = activeTouch else { return }
for touch in touches {
if touch == active {
// The moving ball stops moving, reset activeTouch to nil
}
}
}
// Probably touchesCancelled should be the same as touchesEnded, or
// maybe you'd want to move the ball back to the starting position;
// depends on your game.
I thought I WAS doing that. Thanks to your simplified template I found where I was messing up. Thank you