Get position of private object in update method - swift

Is there a way I can access a property of an SKSpriteNode (Its position) in the update() method if it is declared and initiated within a specific method? I have a method called shootLaser() that creates an SKSpriteNode like so:
var laser = SKSpriteNode(imageNamed: "LaserDot.png")
And I need to perform an action using the position of "laser" every time a frame is rendered, and I only know of doing that by using the update() method.

You can access the certain node by its name property:
laserNode.name = "laserNode"
After that , you can use childNodeWithName to access certain node by its name:
let laserNode: SKSpriteNode = parentNode.childNodeWithName("laserNode") as SKSpriteNode
or if laser is added directly to the scene:
let laserNode: SKSpriteNode = childNodeWithName("laserNode") as SKSpriteNode

Related

How do you add a child of a custom class to GameScene?

I have a custom class named Test that extends SKShapeNode with 4 SKShapeNodes as its child, and I would like to add them as a child of GameScene. However, when I try to execute addChild() in GameScene, I end up getting the error signal SIGABRT.
In my custom class I declare:
let shapeR = SKShapeNode()
let shapeG = SKShapeNode()
let shapeY = SKShapeNode()
let shapeB = SKShapeNode()
Then in override init(), I call the addChild() methods:
addChild(shapeR)
addChild(shapeG)
addChild(shapeY)
addChild(shapeB)
Finally in GameScene, I iterate through the children with (test is defined as Test()):
for child in test.children {
addChild(child)
}
How do I fix this?
Edit: I need 4 SKShapeNodes since I want 4 different colors in my custom SKShapeNode object.
Nevermind I just had to addChild() the entire class and not just separate SKShapeNodes

Swift 3 (SpriteKit): Create a texture from a node tree

I have been trying to render a node tree into an SKTexture as a possible solution to another question here. I tried searching for an answer to this, and I came across one of Apple's Developer pages (view it here). It says the command which converts a node tree into an SKTexture is this:
func texture(from node: SKNode) -> SKTexture?
Although, the code is incomplete since there is no code which executes the conversion of a node tree to an SKTexture. Am I doing something wrong or what is the complete code that I should use to render a node tree into an SKTexture.
Thanks for any advice, help, and answers!
texture(from:) is an instance method of SKView that takes a node (with zero or more children) as a parameter and returns an optional SKTexture. Since the returned value is an optional, you'll need to unwrap it before using it.
From didMove(to:), you can use the view parameter to create a texture
if let texture = view.texture(from: node) {
let sprite = SKSpriteNode(texture:texture)
addChild(sprite)
}
From other methods in the SKScene subclass, use optional chaining
if let texture = self.view?.texture(from: node) {
let sprite = SKSpriteNode(texture:texture)
addChild(sprite)
}
You can also render the portion of the node-tree's contents inside of a rectangle with
let rect = CGRect(x:-width/2, y:-height/2, width:width, height:height)
if let texture = self.view?.texture(from: node, crop: rect) {
let sprite = SKSpriteNode(texture:texture)
addChild(sprite)
}

How can I make images that act as buttons in Swift?

I have the code for one button on my scene, but I tried using that same code to make another button in the same scene, and it didn't work. Here's the code I have so far:
for touch:AnyObject in touches {
let location = touch.locationInNode(self)
if playGameButton.containsPoint(location) {
let newScene = GameplayScene(size: self.size)
newScene.scaleMode = scaleMode
self.view?.presentScene(newScene)
}
}
Again, that's only one button. When I use that same bit of code for another image, it doesn't work.
A better way to approach this problem would be to use an SKSpriteNode object as your button and set its name property to easily distinguish between multiple buttons. For example, if you have an SKSpriteNode object button1:
button1.name = "first"
Then in your touch method to check which was touched, you can use the name property:
SKNode node = self.nodeAtPoint(location)
if node.name == "first" {
// do something
}

Get location of an SKSpriteNode

I have an SKSpriteNode called "Laser" that is created in a method known as "shootLaser", with its scope being purely local to that method. The shootLaser method is called on a repeating timer, creating a new Laser object every couple of seconds, so I cannot simply declare the Laser object outside any method. I also have a variable known as laserLoc that I want to be always equal to the location of the "Laser" object at any given time. In the update() method (which is called every time a frame is rendered), my idea was to set laserLoc = Laser.position, but since Laser is only local to the shootLaser method, I get a "use of unresolved identifier error". Is there any way around this?
I think you can declare an SKSpriteNode Array and add the Laser to it. Every time a new laser is created you can check that in your update func.
Here is an example:
class GameScene: SKScene{
var checkForNodes = [SKSpriteNode]()
func shootLaser {
/* Your stuff */
var Laser = SKSpriteNode()
checkForNodes.append(Laser)
}
override func update(currentTime: NSTimeInterval) {
super.update(currentTime)
for Laser in checkForNodes {
/* Your Position Setup */
}
}

Swift/SpriteKit - Collisions and Objects

I have a class called Item, and inside there is an instance variable called itemNode which is of type SKSpriteNode. In my GameScene class, when I create an instance of Item I create a physics body that is given to the Item's itemNode. In my collision detection system, when my character's physics body collides with the itemNode's physics body, I want to preform a function on the Item object whose node's physics body just collided. However, the collision system only returns to physics body. How do I access the Item object given only the physics body of the node?
The SKPhyicsBody class has a node property which points to the SKNode instance it is attached to.
Your collision detection code can look something like this:
func didBeginContact(contact: SKPhysicsContact) {
var item: SKSpriteNode
var character: SKSpriteNode
//Change this on the basis of the order of your categoryBitMask values
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
item = contact.bodyA.node as SKSpriteNode
character = contact.bodyB.node as SKSpriteNode
}
else
{
item = contact.bodyB.node as SKSpriteNode
character = contact.bodyA.node as SKSpriteNode
}
//Perform necessary operations on item and character
}
EDIT:
In order to get access to the Item instance that declares the node, you will have to store a variable within the node which points to the Item instance. For this, you can either subclass SKSpriteNode and include a property, or use the userData
property of SKNode
Subclassing:
//New Class
class ItemNode: SKSpriteNode {
static var itemInstance
}
//In the Item class declare the itemNode using this class
let itemNode = ItemNode()
itemNode.itemInstance = self
UserData property:
item.userData = NSMutableDictionary(object: self, forKey: "ItemInstance"))