for(SKNode * node in nodes) in swift - ios

Am new to swift and learning
I use
" for(SKNode * node in nodes) "
for selecting the particular node with its name in objective-C but in swift I need some help to do this. Thanks in advance

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject() as UITouch
let touchLocation = touch.locationInNode(self)
let nodes = self.nodesAtPoint(touchLocation) as [SKNode]
for node in nodes {
if let nodeName = node.name {
if nodeName == "myNodeName" {
println("node tapped")
}
}
}
}
To check if a node is tapped, iterate with for loop. Loop through the SKNodes, and check if the node name matches. Difference is that instead of (SkNode* node) we have :
let nodes = self.nodesAtPoint(touchLocation) as [SKNode]

in SWIFT
for node in nodes {
}

Here is a simple example using "for" loop in swift :
let arrStrings = ["one","two","three","four"]
for str in arrStrings
{
if str=="two"
{
println("\(str)")
}
}

Related

How do I check if the same key exists in an Array?

I am trying to make a RPG game in IOS, with a similar dialogue system in Baldurs Gate. I have created two arrays in a plist file. Like this:
As you can see I have two arrays: PlayerMessage; a list (it will be) of multiple choices that the player can touch and NPCMessages; the text that is displayed when the PlayerMessage is touched
I am at the stage where I can touch on the NPC and it will display a black box (NPCMessageer node) with text from the array (PlayerMessage via the plist file).
However, I don't know how to connect Item 0 in PlayerMessage and NPC Message and if they exist change the Message: SKLabelNode! text to one in NPCMessage. Does anyone know how to compare if another item exist in another array?
Here is the code that I have used:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
for touch in (touches) {
NPC.name = "NPC"
let Location = touch.location(in: self)
var CorrectedLocation = CGPoint()
CorrectedLocation.x = Location.x - LocalCamera.position.x
CorrectedLocation.y = Location.y - LocalCamera.position.y
let node = self.atPoint(CorrectedLocation)
var Message: SKLabelNode!
Message = SKLabelNode(fontNamed: "Trebuchet MS")
if (node.name == "NPC") {
let NPCMessageer = SKSpriteNode (color: UIColor.black, size: CGSize(width:1000, height:1000))
NPCMessageer.zPosition = 99
NPCMessageer.position = CGPoint(x:-500, y:-200)
Message.fontSize = 50
Message.color = UIColor.white; Message.position = CGPoint(x:-500, y:-100)
Message.zPosition = 100
addChild(NPCMessageer)
self.addChild(Message)
for PlayerMessage in NPC.PlayerMessage {
Message.text = PlayerMessage as?String}
let label = self.atPoint(CorrectedLocation)
if label.name == "Message"
{
if NPC.PlayerMessage == NPC.NPCMessage
{
Message.text = NPC.NPCMessage as?String
}
If I understand correctly you want to find a given element from one array in another array.
You can then use firstIdex(of:) and if an element exist use the returned index to set the Message object
let item = PlayerMessage[0] //assuming this is what you want to find
if let index = NPCMessage.firstIndex(of: item) {
let Message.text = NPCMessage[index]
}

Casting as a sksprite node

I keep getting a SIGBRT error on this line of code:
let spriteTapped : SKSpriteNode = (nodeTapped as? SKSpriteNode)!
I am using it to check if my sprite is tapped and which one is tapped, I get this error whenever anything other than a SKSpriteNode is tapped, any ideas on how I might fix this?
If nodeTapped is not a SKSpriteNode then the conditional cast
nodeTapped as? SKSpriteNode
evaluates to nil, and the forced unwrapping with ! crashes.
Better use optional binding:
if let spriteTapped = nodeTapped as? SKSpriteNode {
// ... do something with spriteTapped ...
} else {
// tapped node is not a SKSpriteNode
}
or
guard let spriteTapped = nodeTapped as? SKSpriteNode else {
return // tapped node is not a SKSpriteNode
}
// ... do something with spriteTapped ...
If you have an array of nodes then
for case let spriteTapped as SKSpriteNode in nodesTapped {
// ... do something with spriteTapped ...
}
can be used to iterate over all sprite nodes in the list (and
silently ignore other nodes).
Answer by #Martin R is totally correct.
Let me add more details about detecting which nodes or sprites have been tapped.
If you add this to your scene
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let tappedNodes = nodes(at: location)
let tappedSprites = tappedNodes.compactMap { $0 as? SKSpriteNode }
}
you can easily get the list of all the nodes (tappedNodes) and the sprites (tappedSprites) having the same coordinates of your touch.

Why is my music not playing in reverse when using the property canPlayReverse in Swift?

Im trying to play my music in reverse by using the canPlayReverse property but that is not working. When I try to play it in reverse it goes forward. Here is the code I have below: Thank you!
class GameScene: SKScene, MPMediaPickerControllerDelegate, AVAudioPlayerDelegate {
private var player:AVPlayer! = AVPlayer()
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
//this is for the left turntable
if node.name == "lefttt" {
//lets user rotate left turntable when there is one finger on turntable.
let dy = leftTurntable.position.y - location.y
let dx = leftTurntable.position.x - location.x
let angle2 = atan2(dy, dx)
leftTurntable.zRotation = angle2
let delta = (angle2 - previousAngle); M_PI
if delta > 0 {
print("rotateleft")
if musicPlayer == player.currentItem?.canPlayReverse {
musicPlayer.rate = -1.0
}
} else {
print("rotateright")
musicPlayer.rate = 3.0
musicPlayer.play()
}
previousAngle = angle2
}
When you use asset!, you're telling the compiler that the variable will point to a valid object but your code isn't setting asset to anything non-nil.
In general, avoid '!' whenever possible and test your optionals instead.

iOS Swift SpriteKit didEndContact not working properly

in my app(game) i need to detect contact with water and run action(withKey) while my Node is under water,im doing that with didBeginContact and Update method. But when i move my Node(with touches) from water im using didEndContact to detect whether Node is outof water and stop previous action(withKey) and it could be all fine but sometimes didEndContact not stoping action and do not detect (using print("EndContact")) that contact is ended.
Cheking contact between to nodes:
func didBeginContact(contact: SKPhysicsContact)
{
if let node1 = contact.bodyA.node
{
let entityNode = node1 as! Entity
entityNode.collideWith(contact.bodyB, contact: contact)
}
if let node2 = contact.bodyB.node
{
let entityNode = node2 as! Entity
entityNode.collideWith(contact.bodyA, contact: contact)
}
}
func didEndContact(contact: SKPhysicsContact)
{
if let node1 = contact.bodyA.node
{
let entityNode = node1 as! Entity
entityNode.collideEndedWith(contact.bodyB, contact: contact)
}
if let node2 = contact.bodyB.node
{
let entityNode = node2 as! Entity
entityNode.collideEndedWith(contact.bodyA, contact: contact)
}
}
Entity is subclass of SKSpriteNode, where i declare physics bitmask and so-on. I got Player class and Enemy class based on Entity. In my Player class i got functions that run some code when didBeginContact and didEndContact triggers
override func collideWith(body: SKPhysicsBody, contact: SKPhysicsContact)
{
if let enemy = body.node as? Enemy
{
contactingWater = true
self.runAction(SKAction.scaleBy(1.1, duration: 0.2), withKey: "action")
}
}
override func collideEndedWith(body: SKPhysicsBody, contact: SKPhysicsContact)
{
if let enemy = body.node as? Enemy
{
contactingWater = false
self.removeActionWithKey("action")
}
}
override func update(delta: CFTimeInterval){
}
Also i update my 'Player' on 'MainScene' in Update method. It seems to work fine but as i said sometimes didEndContact do not trigger
override func update(currentTime: NSTimeInterval)
{
if lastUpdateTime > 0
{
dt = currentTime - lastUpdateTime
} else {
dt = 0
}
lastUpdateTime = currentTime
player?.update(dt)
}
I noticed that this"sometimes" occurs
when i move Node into the water and when move back remove my finger ith stil thinks that im in contact with water. Ill be glad to any sugestion, cause im very new in programing) thx

How would I save a label using NSUserDefaults in swift?

I have these two UITextFields and the first texField subtracts the number from the second textField. It then takes the answer and puts it in my SKLabelNode. That works fine. But the problem Im having is that it doesn't save the label. When I quit the app and go back to it it doesnt save the value. What am I doing wrong with my code?
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
var defaults=NSUserDefaults.standardUserDefaults()
var save=defaults.integerForKey("saveCalories")
var touch: UITouch = touches.first as! UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if let number1 = textFieldCaloriesIntake.text.toInt() {
if let number2 = textFieldCaloriesBurned.text.toInt() {
let subtract = number1 - number2
defaults.setInteger(subtract, forKey: "saveCalories")
var showTotalCalories = defaults.integerForKey("saveCalories")
totalCaloriesLabel.text = String(showTotalCalories)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
}
Use this code for Swift
NSUserDefaults.standardUserDefaults().setValue(value, forKey:key)
Save example:
NSUserDefaults.standardUserDefaults().setValue(positionTextField.text!, forKey: "position")
Retrieve example:-
position!.text=NSUserDefaults.standardUserDefaults().stringForKey("position")
Note: remember the key for further retrievals
Save the text of the label in NSUserDefaultinstead
I got it to work by putting the code in the didMoveToView; it saves the label now.

Resources