SpriteKit: Add SKSpriteNodes To The View - swift

I basically want to add a SKSpriteNode to the screen and I have no idea where the mistake it. So I include pictures of my three classes participating in this problem. I created a class for all the background stuff. There I use the function addChild() to add my 56 Nodes to the View but they do not appear on the screen. Theoretically (for me) everything should work.
Hopefully you can help me adding the Nodes to the screen!
Edit: Updated the pictures.

When you call this:
GameScene().addChild(image)
you every time inside for create the local GameScene object, add image to this object and when you move to the next iteration of the loop, this object is destroyed. In fact, after your loop thire is no one GameScene object.
Second, you don't need to use var image = SKSpriteNode() in your hintergrund object. You every time set this reference to new object.
You have the cross references in code, try to make somthing like this:
class GameScene: SKScene {
...
override func didMoveToView(view: UIView) {
hintergrund.setBackgroundForScene(self, width: screenWidht)
}
}
class hintergrund {
...
class func setBackgroundForScene(gameScene: GameScene, width: CGFloat) {
...
for (...) {
...
gameScene.addChild(image)
}
}
}

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

how to add a sprite an existing scene

What is the best way to add a sprite node after a scene has been fully loaded? The sequence looks like this:
1) I build the scene, GameScene().
2) Some time later, I download backend data and I use this info to build a SKSpriteNode in a different class, NodeBuilder().
3) I want to add this node to the instance of my scene that I'd already loaded.
What's the best way to achieve step 3)?
In GameScene:
addChild(yourNode)
For getting and keeping a reference to NodeBuilder:
Creation of NodeBuilder in GameScene:
class GameScene : SKScene {
var nodeBuilder = NodeBuilder() // Create an instance of NodeBuilder
func didMoveToView(skView: SKView) {
nodeBuilder.gameScene = self // Add self as the instance of GameScene that nodeBuilder has reference to
}
}
In NodeBuilder:
class NodeBuilder {
var gameScene : GameScene! // This is how you keep your reference
func addNodeToGameScene(node: SKNode) {
self.gameScene.addChild(node)
}
addNodeToGameScene(aNode) // This is how you would call the method to add a node to GameScene from NodeBuilder
}

SKSpriteNode Automated movement

I'm making my first game, it will be similar to Mario. (using swift)
Have started to make some enemies they will need to move left and right and respond to collisions, I can do this for my player node as I call player.update() function from the SKScene update function,
override func update(currentTime: NSTimeInterval)
{
player.update()
}
My question is:
For enemyX , how can I get the node to update since SKSpriteNode does not have a default update function that can be overridden and from my game scene
I do not want really write some thing like:
override func update(currentTime: NSTimeInterval)
{
player.update()
enemyX.update()
enemyY.update()
enemy001.update()
...
enemy100.update
}
Do you see what I mean, how do I get around this, does SKSpriteNode need to be a different class?
Maybe actions?
let moveLeft = SKAction.moveByX( 200, y:0, duration: 5)
self.runAction(moveLeft, completion: {
print("----> move left Complete")
})
Thanks.
you subclass SKSpriteNode and and an update method inside that class. then in your update method in your scene you do exactly what you said
player.update()
enemy.update()
etc.
Don't recommend using SKAction unless the behavior of your enemies is extremely simple.

Reuse same sprite node within multiple scenes in sprite kit using Swift

I create sprite node in my GameScene as the following. I would like to reuse createNodeA1 or nodeA1 in other SKScene. How can I do that?
import SpriteKit
class GameScene: SKScene {
var nodeA1: SKNode!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(size: CGSize) {
super.init(size: size)
// Add sprite node to the scene
nodeA1 = createNodeA1()
addChild(nodeA1)
}
}
// Create dot 1
func createNodeA1() -> SKNode {
let spriteNode = SKNode()
spriteNode.position = CGPointMake(CGRectGetMidX(self.frame)/1.5, CGRectGetMidY(self.frame)/2.0)
let sprite = SKSpriteNode(imageNamed: "dot_1")
sprite.zPosition = 3.0
sprite.name = "A1_Broj"
spriteNode.addChild(sprite)
return spriteNode
}
}
There is a few ways to do this.
You could subclass your other scenes to be subclass of the scene with the loadNode function which gives those scenes access to that function.
I asked a question about this last year
Swift multiple level scenes
Another way that might be a bit easier if you are not comfortable with scene subclassing is to just create a subclass of the node itself.
So you create a class
enum EnemyType {
case Normal
case Special
}
class NodeA1: SKSpriteNode {
init(imageNamed: String, enemyType: EnemyType) {
let texture = SKTexture(imageNamed: imageNamed)
if enemyType == .Normal {
super.init(texture: texture, color: SKColor.clearColor(), size: texture.size())
else {
// other init
}
self.zPosition = 1
self.name = ""
// add physics body, other properties or methods for the node
}
}
Than in your SKScenes you can add the node in the init method like so
nodeA1 = NodeA1(imageNamed: "ImageName", enemyType: .Normal)
nodeA1.position = ....
addChild(nodeA1)
this way ever scene where you add the node will use the subclass and therefore include all the properties, set up etc for that node. Another benefit with subclassing is that you could loop through all your nodes using
self.enumerateChildNodesWithName...
and than call custom methods on all nodes.
If you want to subclass your scenes than you would create your baseScene
class BaseScene: SKScene {
// set up all shared stuff in didMoveToView
// have your node function here
// touches began
// physics word and contact collision
// all other stuff that needs to be shared between all level scenes
}
Than your subsequent level scenes would look something like this
class Level1Scene: BaseScene {
override func didMoveToView(view: SKView) {
super.didMoveToView(view) // This lines imports all stuff in BaseScene didMoveToView
// do level 1 specific setUps.
// you can call any function or property from BaseScene, e.g the loadNode function.
}
You than load you level scenes as usual, e.g you transition to level 1 scene and it will automatically use/have access to all the superclass methods and sprites (BaseScene).
So you never call baseScene directly, its gets called automatically.
This applies for other methods in baseScene too, so say you have a Update method in BaseScene.
override func update(currentTime: CFTimeInterval) {.... }
This will work across all your level scenes which are subclasses of BaseScene.
But what happens if you need to add some specific stuff to the update method only relevant in 1 level scene and not all level scenes?
It would be the same process, you create a new update func in the LevelScene and call super.
override func update(currentTime: CFTimeInterval) {
super.update(currentTime) // this calls the baseScene Update method
/// specific stuff for that level only
}
Super simply means the super class of the currentScene, which is BaseScene if the scene is a subclass of it.
Is this helping?
This is additional answer information in terms of subclass of the baseScene. We can create node1thru node10 all in baseScene. Then in Leve1Scene which is subclass of the baseScene, all we have to do is in didMoveToView function state node1.position = CGPointMake(....) for each node that we need in Level1Scene where we would specify node's position.
If we do not need to load all of the 10 nodes in Level1Scene, for example, let's say we don't need to load to the scene node10 we can simply in didMoveToView function just state node10.removeFromParent() and this node will not be loaded to Level1Scene but rest of 9 nodes will.
Note that this example uses only 10 nodes, but you can go with any number of nodes in your baseScene.
This way of subclassing will save you a lot repeatable code in subclasses.

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 */
}
}