SKSpriteNode touch detected swift - xcode

I am having trouble with detecting a specific node being touched. Here is what i have to far.
let playagain = SKSpriteNode(imageNamed: "PlayAgain.png")
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
}
then when the player dies these two nodes come up.
playagain.position = CGPoint(x:frame.size.width * 0.5, y: frame.size.height * 0.5)
addChild(playagain)
gameover.position = CGPoint(x:frame.size.width * 0.5, y: frame.size.height * 0.75)
addChild(gameover)
everything above works. the node comes on the screen where i asked i just can't seem to get it to show i clicked it.
as you can see the node is called playagain, when the playagain node is clicked i want to be able to refresh the game. what i have so far is below.
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in touches {
let location = (touch as! UITouch).locationInNode(self)
let play = self.nodeAtPoint(location)
if play.name == "playagain" {
println("touched")
}
}
}
thanks!

Are you not using the latest Xcode? Your touches began code should not run with swift 2 and Xcode 7.
Try this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if playagain.containsPoint(location) {
/// playagain was pressed, do something
}
}
}
or this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(location)
if touchedNode == playagain {
/// playagain was pressed, do something
}
}
}

Related

Getting a vector from a touch location in swift 3

As the title says, how can I accomplish this? I can get the first touch but I don't know how to get the last touch if it is a swiping gesture. With the following code I get the error: value of type 'Set' has no member 'last'. Not really sure how to get the position when the touch is released.
override func touchesMoved(_ touches: Set<UITouch>, with: UIEvent?){
let firstTouch:UITouch = touches.first! as UITouch
let lastTouch:UITouch = touches.last! as UITouch
let firstTouchLocation = firstTouch.location(in: self)
let lastTouchLocation = lastTouch.location(in: self)
}
I want to get the location of the first point and the location of the second point. Then I would like to use the duration of the swipe, the size of the line, and the angle of the line to create an impulse vector to use on an SKNode. Is there any way to extract this information using the UITouch? Any help is greatly appreciated. Thanks for your time!
I also have basic touches on the screen that run functions
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch:UITouch = touches.first! as UITouch
let touchLocation = touch.location(in: self)
if playButton.contains(touchLocation) && proceed == true{
playSound1()
Ball.physicsBody?.affectedByGravity = true
proceed = false}
else if infoButton.contains(touchLocation) && proceed == true{
playSound1()
loadScene2()}
else {}
}
You have to store the values in touches began and compare with the values in touches ended and then do the calculations there. Note that a touch can be canceled by something like a phone call so you need to anticipate that as well.
class v: UIViewController {
var startPoint: CGPoint?
var touchTime = NSDate()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard touches.count == 1 else {
return
}
if let touch = touches.first {
startPoint = touch.location(in: view)
touchTime = NSDate()
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
defer {
startPoint = nil
}
guard touches.count == 1, let startPoint = startPoint else {
return
}
if let touch = touches.first {
let endPoint = touch.location(in: view)
//Calculate your vector from the delta and what not here
let direction = CGVector(dx: endPoint.x - startPoint.x, dy: endPoint.y - startPoint.y)
let elapsedTime = touchTime.timeIntervalSinceNow
let angle = atan2f(Float(direction.dy), Float(direction.dx))
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
startPoint = nil
}
}

touchesMoved doesn't record all points in a UIView (Swift implementation)

I am new to coding in general. Recently starting coding in Swift.
Working on a simple Swift based drawing app in which I need to record an array of points over which user touches screen and moves finger.
I am using touchesMoved to record touch locations in a UIView. touchesMoved doesn't record all the points if user moves finger fast enough. If finger movement is slow, it records all points. I looked at earlier questions regarding this on this forum but couldn't figure out how to implement those. Any suggestions or direction on where to look for the answer will be highly appreciated.
Attached is the code I am using
import UIKit
class SketchView: UIView {
var lines = [Line]()
var lastPoint: CGPoint! //this is to track last touch of the user
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first! as UITouch
lastPoint = touch.locationInView(self)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first! as UITouch
let newPoint = touch.locationInView(self)
lines.append(Line(start: lastPoint, end: newPoint))
lastPoint = newPoint
self.setNeedsDisplay()
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
print(" Sketch points number is \(lines.count)")
}
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
CGContextBeginPath(context)
for line in lines {
CGContextMoveToPoint(context, line.start.x, line.start.y)
CGContextAddLineToPoint(context, line.end.x, line.end.y)
}
//CGContextSetLineCap(context, .Round)
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1)
CGContextSetLineWidth(context, 5)
CGContextStrokePath(context)
}
}
Just to confirm that points are missing in my array, in the image below I am showing the x-coordinates stored in the array for a line a drew on screen.
Thanks.

How do I get my node to rotate even if my finger is outside the node?

Ill try to explain this the best way I can. I have this circle that I can rotate when my finger is moving on the circle. The problem Im having is that when Im rotating the circle and I move my finger outside the circle the rotation stops. I would like it to still have the touch even if my finger is outside the node. It works when Im in a single view controller but in spritekit I cant figure it out.
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if node.name == "circle" {
let dy = circle.position.y - location.y
let dx = circle.position.x - location.x
let angle2 = atan2(dy, dx)
circle.zRotation = angle2
}
}
}
Declare an optional SKNode to hold the current rotating node like var rotatingNode:SKNode?. You can override touchesBegan.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if node.name == "circle" || node.name == "rightCircle" {
self.rotatingNode = node
}
}
}
From your comment it seems like you have other code in touchesMoved than what is posted in your question. But if you want to rotate either circle or rightCircle then say something like:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let dy = self.rotatingNode?.position.y - location.y
let dx = self.rotatingNode?.position.x - location.x
let angle2 = atan2(dy, dx)
self.rotatingNode?.zRotation = angle2
}
}
Then in touchesEnded:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.rotatingNode = nil
}

Changing the colour of a SKShapeNode when touched?

I have a game where i touch a node and it runs some code. How do I change the SKShapeNode's color when touched? I tried to use node.fillColor = SKColor.blackcolor() for example but it says that I cannot do that even though thats how i originally created the SKShapeNode's color in the first place.
This is all writing within touches began method.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let positionOfTouch = touch.locationInNode(self)
let node = nodeAtPoint(positionOfTouch)
node.userInteractionEnabled = true
node.fillColor = UIColor.whiteColor()
This is the code I am using. But it keeps saying "Value of type SKNode has no member "fillColor"...But "fillColor" works in my DidMoveToView.
Thanks
The node you are likely to touch may be a parent or child node - an SKNode, not an SKShapeNode. That's what nodeAtPoint returns, and a generic SKNode doesn't have a fillColor. You need to check it is the class you are expecting by testing. Something like...
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let positionOfTouch = touch.locationInNode(self)
if let node = nodeAtPoint(positionOfTouch) as? SKShapeNode {
node.userInteractionEnabled = true
node.fillColor = UIColor.whiteColor()

SKSpriteNode drag movement by touch

I'm trying to drag a SKSpirteNode around the screen by touching the screen. But I want to be able to do a constant movement of the Sprite, currently my code only moves the sprite to the location of my touch but if I hold and move the sprite will not follow. Moreover I don't want to "have" to touch the SKSpriteNode to activate the movement, I want to touch anywhere on the screen and to have a movement response from that SKSpriteNode.
Here is my current code:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// SpriteNode I want to drag around
basket = SKSpriteNode(texture: basketTexture)
self.addChild(basket)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
var nodeTouched = SKNode()
var currentNodeTouched = SKNode()
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
nodeTouched = self.nodeAtPoint(location)
basket.position = location
}
Thank you any help appreciated.
I solved this by using the func touchesMoved instead of touchesBegan and works perfectly and smoothly. here is the final code:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// SpriteNode I want to drag around
basket = SKSpriteNode(texture: basketTexture)
self.addChild(basket)
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
var nodeTouched = SKNode()
var currentNodeTouched = SKNode()
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
nodeTouched = self.nodeAtPoint(location)
basket.position = location
}

Resources