(Swift + Spritekit) - remove node and its data entirely - ios

I'm working a little game for iOS.
I've a SKSpriteNode in my scene - when I remove it with "removeFromParent" and touch the area it was last in, I still get the function.
My code is as following:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if tapToPlayNode.containsPoint(location){
tapToPlayNode.removeFromParent()
startNewGame()
}
}
}
func startNewGame(){
//Starts a new game with resetted values and characters in position
println("Ready.. set.. GO!")
//Shows the ui (value 1)
toggleUiWithValue(1)
}
In other words, I get "Ready.. set.. GO!" output when I touch the area even after it was deleted.
Any clues?
Bests,

Your tapToPlayNode is still retained by self and is removed from it's parent.
You should make it optional var tapToPlayNode:SKSpriteNode?and nil it after remove it from it's parent like this:
if let playNode = self.tapToPlayNode {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if playNode.containsPoint(location) {
playNode.removeFromParent()
startNewGame()
self.tapToPlayNode = nil // il it here!
break
}
}
}
You can also avoid to keep a reference of your tapToPlayNode and give it a name when initializing it like this:
node.name = #"tapToPlayNodeName"
// Add node to scene and do not keep a var to hold it!
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
// Retrieve the ode here
let tapToPlayNode = container.childNodeWithName("tapToPlayNodeName")!
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if tapToPlayNode.containsPoint(location){
tapToPlayNode.removeFromParent()
startNewGame()
}
}
}

Related

Touch detection of SKSpriteNode with child nodes

I'm trying to trigger a touch event on a SKSpriteNode where it's child node is tapped on. When the child node it touched, the event isn't triggered. I have found a hack work around using .parent but doesn't feel like the most efficient or elegant way of doing is.
Please see code below:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first! as UITouch
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if node is PlanListItem || node.parent is PlanListItem {
for plan in planListItems as [PlanListItem] {
plan.selected = false
}
// Some more code...
}
}
Help much appreciated.
You can do this inside the node subclass:
class PlanListItem:SKSpriteNode {
var isSelected: Bool = false
override init(texture size etc) {
//your init
self.userInteractionEnabled = true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("PlanListItem touched")
isSelected = !isSelected
}
}

how to code UIbuttons/IBactions in touches methods for a Sprite kit game

In my previous app (single view application) i used touch down and touch up inside IBActions for buttons in my game. However in a SpriteKit game you have to completely create the scene and i am having a hard time coding my touchesBegan method.
Here is my basic movement method/function:
func heroMovementLeft () {
hero.position = CGPointMake(hero.position.x - 0.5,hero.position.y);
}
here is my Left arrow node, i would like the HeroMovementLeft method to be called upon touching the LeftArrow
func LeftArrow () {
let LeftArrow = SKSpriteNode(imageNamed: "Left Arrow.png")
LeftArrow.position = CGPointMake(30, 30)
self.addChild(LeftArrow)
}
Here's where I am at right now for coding the touchesBegan method
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
}
}
Do I create an if statement? Do I make touch a variable? What do I need to write in my touches began method so that my hero will move when left arrow is touched. I have looked all over online and cannot find an answer to this question, please help.
You basically have 2 options to identify your sprites
1) make them global properties to your scene
class YourScene: SKScene {
var leftArrow: SKSpriteNode!
override func didMoveToView(view: SKView) {
}
func leftArrow() {
leftArrow = SKSpriteNode(imageNamed: "Left Arrow.png")
leftArrow.position = CGPointMake(30, 30)
addChild(leftArrow)
}
}
than in touches began you can get the location like so
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
let node = nodeAtPoint(location)
if node == leftArrow {
heroMovementLeft()
}
}
}
Option 2 is to give your sprites names
func leftArrow() {
let leftArrow = SKSpriteNode(...)
leftArrow.name = "LeftArrow"
...
}
and than check for those names in the touches began method
....
if node.name == "LeftArrow" {
heroMovementLeft()
}
As a side note you should start your properties or func with small letters and only start classes, structs and protocols with capital letters.

Moving objects according to touchesMoved

So I'm trying to move an object using the touches moved function, however I'm not sure how to do that when the coordinates are not predetermined. This is what I've got going :
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
var touch: AnyObject? = touches.anyObject()
var point = touch?.locationInView(self.view)
}
So basically I'm making the point variable the coordinates (points).
Then what needs to happen is that i move an object (in this case Label1) to that location:
func MoveObject(point) {
Label1.frame.origin = ( /* Here would the ´point´ be */ )
}
Also keep in mind that later when this problem is out of the way I'm going to change the location so its not where you touch but it moves accordingly. I don't know if that matters really but I'm just saying in case it does ;)
What about
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
var touch: AnyObject? = touches.anyObject()
var point = touch?.locationInView(self.view)
moveObject(point)
}
...
func MoveObject(point) {
Label1.center = point
}

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)
}
}

Swift access methods of touched Node

Im dragging a SKSpriteNode around with the following method
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
for touch in touches {
let location = touch.locationInNode(self)
var touchedNode = nodeAtPoint(location)
if touchedNode.isKindOfClass(Card) {
touchedNode.position = location
}
}
}
the if statement is confirming that it;s pif a specific class, how can I now call methods and access properties this node?
You can use this syntax:
if let cardNode = touchedNode as Card {
cardNode.position = location
// cardNode is of type card. You can access all its
// methods and properties
}

Resources