touchesMoved: How to know when the touch ended? - ios

I have a ball that I want to move around (Spritekit) and I want to set a velocity so when the player move the ball then he moves his finger from the screen the ball will move and it will have it's own velocity depinding on some calculations
the question :
this is my code , how can I know when the player is moving his finger from the screen ?!
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
if let touch = touches.first as? UITouch{
var location = touch.locationInNode(self)
ball6.position = location
}

Use this method:
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
//your code
}

Related

How do I get the location of a UI touch in Sprite Kit?

I would like to get the location of the touch in the UI, and use that location to determine what direction the sprite runs. For example, if the touch is on the left side of the screen, the user runs left, and if the touch is on the right side of the screen, the user runs right.
Try something like this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let position = touch.locationInView(view)
print(position)
}
}
#KnightOfDragon's answer is the right one here.
You should use directly
func locationInNode(_ node: SKNode) -> CGPoint
More about Touch events in SpriteKit over here: documentation
As KnightOfDragon mentioned for SpriteKit the correct way would be
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self) // self is the current SKScene
let node = nodeAtPoint(location)
// To get the touched half of the screen I do this
if location.x < CGRectGetMidX(self.frame) {
// left half touched, do something
}
if location.x > CGRectGetMidX(self.frame) {
// right half touched, do something
}
}
}

Exceeding the maximum number of touches makes the program not to call the touchesEnded method?

Ive just started learning programming in general and ran into a problem:
I have read some articles about that the iPhones are only capable of tracking 5 touches or so... But I realised that when I touch the screen with e.g. 7 fingers at once, my program-let stops working.
So, anyone knows, which parts of the code malfunctions when I am touching the screen way too many times at once?
(I am a newbie.)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first!
touchLocation = touch.locationInNode(self)
nrTouches += touches.count
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
nrTouches -= touches.count
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first!
touchLocation = touch.locationInNode(self)
}
override func update(currentTime: CFTimeInterval) {
if nrTouches > 0 {
touchingLabel.text = "touching"
} else {
touchingLabel.text = "not touching"
}
}
So, in the case I am touching with 7 fingers at once, "touching" will be displayed all the time.
tankyuu
You're missing touchesCancelled, which gets called when the 6th finger is put down:
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
if let touches = touches {
nrTouches -= touches.count // same logic as touchesEnded
}
}
An interesting note: The iPad can handle 11 touch events. More on that here.

How to apply a basic vector to physics body in Swift 2.0

I am making a very simple space game; I can't seem to get the last line to work. Ideally, I want to get the spacey to move to up when the screen is touched. Here is my code:
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
touch.locationInNode(self)
spacey.physicsBody!.velocity = (CGVectorMake(0, 0))
spacey.physicsBody!.applyImpulse(0, atPoint: 25)
Does anyone have any idea how to do this?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
_ = touch.locationInNode(self)
spacey.physicsBody!.velocity = CGVectorMake(0, 0)
spacey.physicsBody!.applyImpulse(CGVectorMake(0, 25))
The solution was to change touch in touches to use _ in swift 2.0

locationInNode returning erroneous results

I have a subclass of SKNode called Player which pretty much consists of this: http://hub.ae/blog/2014/03/26/soft-body-physics-jellyusing-spritekit/ converted to swift (With a few changes). I've allowed the user to move the player node with his finger with the following code:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
player.runAction(SKAction.moveTo(touch.locationInNode(world), duration: 1))
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
player.runAction(SKAction.moveTo(touch.locationInNode(world), duration: 1))
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
player.removeAllActions()
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
player.removeAllActions()
}
*As a note, the 'world' var you see is just another SKNode. 'player' is a child of this node.
This looks like it should work, however the node moves in very strange directions. This is an example of how it looks:
http://gyazo.com/87b0d09101bbbfd3ac0f2a3cdbf42e4c
How can I fix this? I found that settings the anchor point of the scene to 0.5 fixes this issue, however then the physics body of 'player' node gets messed up.
I had same problem but i can not remember if it is how i fixed it. Try changing this:
world > self
player.runAction(SKAction.moveTo(touch.locationInNode(world), duration: 1))
To:
player.runAction(SKAction.moveTo(touch.locationInNode(self), duration: 1))
If i am wrong let me know :)
EDIT
set anchor point to (0.5,0.5) and write those 2 methods to center on your node.
override func didSimulatePhysics() {
camera.position = CGPointMake(player.position.x, player.position.y);
centerOnNode(camera)
}
func centerOnNode(node: SKNode){
var positionInScene : CGPoint = convertPoint(node.position, fromNode: node.parent)
world.position = CGPointMake(world.position.x - positionInScene.x, world.position.y - positionInScene.y)
}

touchesMoved when two nodes across swift

I had a problem with movning some nodes around but I found a way (finally) but then I faced a problem which is : when two nodes gets across the touch will move from one node to the other ! but what I want is when I touch a node I will move it until I move my finger from the screen
here is my code :
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
var location = touch.locationInNode(self)
let node = nodeAtPoint(location)
if node == firstCard{
firstCard.position = location
}else if node == secondCard{
secondCard.position = location
println("Second Card Location")
println(secondCard.position)
}else{
println("Test")
}
}
}
You need to keep track of the SKNode the finger touched in touchesBegan
First thing to remember is the the same UITouch object is returned for each finger in touchesMoved with different locations. So we can keep track of the each touch in the node using a touchTracker dictionary.
var touchTracker : [UITouch : SKNode] = [:]
Also give a name to each card, so that we can keep track of the nodes that need to be moved. For example.
card1.name = "card"
card2.name = "card"
In touchesBegan, we will add the node that is under the touch to the touchTracker.
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "card") {
touchTracker[touch as UITouch] = node
}
}
}
When a touch is moved inside touchesMoved, we will get the node back from the touchTracker and update its position.
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
for touch in touches {
let location = touch.locationInNode(self)
let node = touchTracker[touch as UITouch]
node?.position = location
}
}
In touchesEnded, we update the final position again, and remove the touch key-value pair from touchTracker.
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
for touch in touches {
let location = touch.locationInNode(self)
let node = touchTracker[touch as UITouch]
node?.position = location
touchTracker.removeValueForKey(touch as UITouch)
}
}

Resources