1

I have a component:

class Test: GKComponent {
    override init() {
        super.init()
        print("init ran")
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        print("coder init ran")
    }
}

I also have a subclass:

class Testing: SKSpriteNode {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

    }
}

So in my scene editor, I have a sprite. In the editor I subclass it to Testing.

Also in the scene editor I add the component Test.

When I run the project, it runs fine, and it prints both print statements in the Component subclass.

  1. Why does it use both init functions and how do I get it to use only 1?

  2. How would I add something in this component like an action or something... Say I want the sprite to rotate for example? How would I do this?

Thank you for any help...

Fluidity
  • 3,985
  • 1
  • 13
  • 34
Discoveringmypath
  • 1,049
  • 9
  • 23

1 Answers1

1

1) I guess you do not understand what a component is, A component is not the same thing as an SKSpriteNode, in fact they are 2 completely different things with almost no relationship to each other. When you place a node on the scene with the scene builder, behind the scenes it makes an instance of GKEntity and GKSKComponent automatically. GKSKComponent is the component that holds the SKSpriteNode. Your Test component is a component that does something else. Everything is compartmentalized. Best example, think of a bicycle. The wheels are a component, the chain is a component, the brakes are a component, each that serve a very unique purpose. You need to create (init) all of these objects to get a bicycle.

2) To get other components to work with your SKSpriteNode, you need to get to the entity. The component should have access to it, so you just need to do self.entity. Then you need to find the GKSKComponent, which will have a link to the node you are looking for so that you may apply actions to it.

Here is my class I have made to make it easier for Components to access the node

import GameplayKit

class NodeComponent : GKComponent
{
    public private(set) lazy var node : SKNode = self.entity!.component(ofType: GKSKNodeComponent.self)!.node

    func resetNode(to node:SKNode)
    {
        self.node = node;
    }

}
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44
  • I knew that a component is not a sprite. I was basically asking how to access the sprite from the component so that I can do stuff to the sprite within the component. So make a rotate component for example. If I can use let node = self.entity(component: GKSKComponent.self) to access the node that solves that issue. I wasn't aware of the GKSKComponent so that answers Question 2, thank you... – Discoveringmypath Sep 25 '17 at 15:56
  • Yeah, I actually made a subclass of GKComponent so that any component I needed the node would get it – Knight0fDragon Sep 25 '17 at 15:58
  • For question 1. I am just wondering about why both init functions are running, I'm still not sure based off your answer. But with experimenting I noticed that the aDecoder init function runs because it is implemented in the editor. Also, the super.init(aDecoder) makes a call to the other init() which I guess makes sense. I must override the init() otherwise it crashes because it needs to be implemented. But I'm still unsure why I have to add it because I assumed there is a init() within super, because of my override. But it works. – Discoveringmypath Sep 25 '17 at 16:00
  • Is the syntax correct for accessing the node? I would use GKSKComponent.self? – Discoveringmypath Sep 25 '17 at 16:01
  • Because they are 2 different things, why would they not both init? You need to create a component, and you need to create a sprite – Knight0fDragon Sep 25 '17 at 16:03
  • It is 2 init functions within the Component. They print from the component class. – Discoveringmypath Sep 25 '17 at 16:07
  • OH, you are saying in Test, why are both being called, I got that confused. it gets called because GKComponents `required init?(coder aDecoder: NSCoder) ` uses `init()` to initialize, so it basically looks like this:`class GKComponent{required init?(coder aDecoder: NSCoder) { init();//Decode}` – Knight0fDragon Sep 25 '17 at 16:07
  • okay that makes sense. I can change the super call to super.init() within the ADecoder init function and it won't call my init() function. Would there be any reason to do it this way or not? – Discoveringmypath Sep 25 '17 at 16:10
  • Just do everything in your `init()` since you know `decoder init` has to call it. – Knight0fDragon Sep 25 '17 at 16:10