1

I am currently building a game and I want to use Gameplaykit to organise the elements.

I discovered the concept of ECS (Entity Component System) that enables to put functionality in small blocks (called components) that can than be added to an entity to give it functionality.

I would like to use it combined with SpriteKit, my first idea was of course to create a SpriteComponent, but since I am also using the physics engine of SpriteKit, I am wondering how I should make the PhysicsBodyComponent, because for this component to work it would need direct access to the physics body of my SpriteKit node, so it would be dependent of the SpriteComponent, but isn't it wrong for components to be dependent on each other ?
How should I do that ?

Thank you.

Pop Flamingo
  • 3,023
  • 2
  • 26
  • 64

1 Answers1

2

It depends how you want to structure your components. Like you said its best to keep them as flexible, reusable and independent of each other as much as possible.

So I would just create a simple render component like you want to. This is what I use in my games.

 import SpriteKit
 import GameplayKit

 /// GK sprite component
 class SpriteComponent: GKComponent {

     // MARK: - Properties

     /// The rendered node
     let node: SKSpriteNode

     // MARK: GKComponent Life Cycle

     /// Init with image
     init(imageNamed: String) {
         node = SKSpriteNode(imageNamed: imageNamed)
     }

     /// Init with texture
     init(texture: SKTexture) {
         node = SKSpriteNode(texture: texture)
     }
 }

In your entity classes you add the component as usual

 class Player: GKEntity {

     override init() { // pass in an image name if you need to
        super.init()

        let spriteComponent = SpriteComponent(imageNamed: "Player")
        addComponent(spriteComponent)
     }
 }

Than you add the entity to the scene and position it. Once a component is added to an entity you can use the component(ofType: ...) method to access its properties, in this case the node property, and do something with them.

 class GameScene: SKScene {

     // code to add entity to scene
     ...

     // position entity 
     if let playerNode = player.component(ofType: SpriteComponent.self)?.node {
        playerNode.position = CGPoint(...)
    }

Go back to your entity class and add the physics body after you added the sprite component.

 ... 
 addComponent(spriteComponent)

 // Set physics body
 if let sprite = component(ofType: SpriteComponent.self)?.node { // component for class is an optional and nil until component is added to entity.
      sprite.physicsBody = SKPhysicsBody(...
      sprite.physicsBody?.categoryBitMask = ...
      ...
 }

This way all your entities can use 1 render component but have different physics bodies on them and use different positions.

You could create a physics body component and pass into the init method the bit masks etc and the node you want it to be added to. However I think thats makes it quite messy so I prefer this way.

If you do need to make components dependent of each other remember that each GKComponent has an entity property you can use. I would try to avoid this as much as possible to keep your components more flexible.

  class SomeComponent: GKComponent {

      func test() {
         entity?.component(ofType: SomeOtherComponent.self)?.someMethod() // only works if this component  is added to entity (entity?) and the other component is also added to entity (...self)?.

       }

  class SomeOtherComponent: GKComponent {

      func someMethod() {

      }
  }

If you need more info you should read these articles, they are very good.

https://www.raywenderlich.com/119959/gameplaykit-tutorial-entity-component-system-agents-goals-behaviors

http://code.tutsplus.com/tutorials/an-introduction-to-gameplaykit-part-1--cms-24483

Hope this helps

crashoverride777
  • 10,581
  • 2
  • 32
  • 56
  • Thank you ! But, you don't have any PhysicsBody component here... isn't it ? – Pop Flamingo Sep 08 '16 at 14:47
  • What should I do if I want to have a PhysicsBody component ? – Pop Flamingo Sep 08 '16 at 14:48
  • Yeah like i said in my answer I prefer to add the physics bodies in the entity class instead of doing a component. Physics bodies tend to be different for each entity anyway. – crashoverride777 Sep 08 '16 at 14:49
  • if you want a component you will need to have a long init method to set all the properties. I think thats messy. Any particular reason you want a component for physics bodies? – crashoverride777 Sep 08 '16 at 14:50
  • Actually, I thought it wouldn't be that bad to have a physics component that would have no direct link with SpriteKit, as it would enable me to change the render engine/physics engine more easily, its pretty unlikely that I will ever do that, tough. – Pop Flamingo Sep 08 '16 at 14:53
  • On the other hand, even if it wasn't that much useful for my case, I thought it would be interesting to know what to do when two components are dependent of each other... – Pop Flamingo Sep 08 '16 at 14:54
  • In fact, since in SpriteKit, a physics body is attached to a node, I was wondering how to make a component that would be independent... – Pop Flamingo Sep 08 '16 at 14:55
  • Yeah the idea is that components should never be dependent of each other, otherwise it kind of defeats the point. Physics bodies tend to be different for each unique entity and there are so many properties (dynamic, affectedByGravity) that it will make your life much harder to make that into a component. – crashoverride777 Sep 08 '16 at 14:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122918/discussion-between-trevor-anne-denise-and-crashoverride777). – Pop Flamingo Sep 08 '16 at 14:56
  • Thank you for your help. – Pop Flamingo Sep 08 '16 at 15:26
  • You are very welcome. I just updated the answer with some more detail. Happy coding. – crashoverride777 Sep 08 '16 at 15:27