Выберите, как разделить функциональность между моими компонентами в ECS

В настоящее время я создаю игру и хочу использовать Gameplaykit для организации элементов.

Я открыл для себя концепцию ECS (системы компонентов объектов), которая позволяет размещать функциональные возможности в небольших блоках (называемых компонентами), которые затем можно добавлять к объекту для придания ему функциональности.

Я хотел бы использовать его в сочетании со SpriteKit, моей первой идеей было, конечно, создать SpriteComponent, но поскольку я также использую физический движок SpriteKit, мне интересно, как мне сделать PhysicsBodyComponent, потому что для того, чтобы этот компонент работал потребуется прямой доступ к физическому телу моего узла SpriteKit, поэтому он будет зависеть от SpriteComponent, но разве не неправильно, чтобы компоненты зависели друг от друга?
Как мне это сделать?

Спасибо.


person Trevör    schedule 06.09.2016    source источник


Ответы (1)


Это зависит от того, как вы хотите структурировать свои компоненты. Как вы сказали, лучше всего сделать их максимально гибкими, многоразовыми и независимыми друг от друга.

Поэтому я бы просто создал простой компонент рендеринга, как вы хотите. Это то, что я использую в своих играх.

 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)
     }
 }

В ваших классах сущностей вы добавляете компонент как обычно

 class Player: GKEntity {

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

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

Затем вы добавляете объект на сцену и позиционируете его. Как только компонент добавлен к объекту, вы можете использовать метод component(ofType: ...) для доступа к его свойствам, в данном случае к свойству узла, и что-то делать с ними.

 class GameScene: SKScene {

     // code to add entity to scene
     ...

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

Вернитесь к своему классу сущностей и добавьте физическое тело после того, как вы добавили компонент спрайта.

 ... 
 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 = ...
      ...
 }

Таким образом, все ваши объекты могут использовать один компонент рендеринга, но иметь на них разные физические тела и использовать разные позиции.

Вы можете создать компонент физического тела и передать в метод инициализации битовые маски и т. д., а также узел, к которому вы хотите его добавить. Однако я думаю, что это делает его довольно грязным, поэтому я предпочитаю этот способ.

Если вам нужно сделать компоненты зависимыми друг от друга, помните, что каждый GKComponent имеет свойство сущности, которое вы можете использовать. Я бы постарался избежать этого, насколько это возможно, чтобы ваши компоненты были более гибкими.

  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() {

      }
  }

Если вам нужна дополнительная информация, вы должны прочитать эти статьи, они очень хороши.

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

Надеюсь это поможет

person crashoverride777    schedule 07.09.2016
comment
Благодарю вас ! Но у вас здесь нет компонента PhysicsBody... не так ли? - person Trevör; 08.09.2016
comment
Что мне делать, если я хочу иметь компонент PhysicsBody? - person Trevör; 08.09.2016
comment
Да, как я уже сказал в своем ответе, я предпочитаю добавлять физические тела в класс сущностей, а не делать компонент. Физические тела, как правило, различны для каждой сущности. - person crashoverride777; 08.09.2016
comment
если вам нужен компонент, вам понадобится длинный метод инициализации для установки всех свойств. Я думаю, это грязно. По какой-то конкретной причине вам нужен компонент для физических тел? - person crashoverride777; 08.09.2016
comment
На самом деле, я подумал, что было бы не так уж плохо иметь физический компонент, который не имел бы прямой связи со SpriteKit, так как это позволило бы мне легче менять движок рендеринга/физический движок, маловероятно, что я когда-либо буду это делать. , жесткий. - person Trevör; 08.09.2016
comment
С другой стороны, даже если это было не так уж полезно для моего случая, я подумал, что было бы интересно узнать, что делать, когда два компонента зависят друг от друга... - person Trevör; 08.09.2016
comment
На самом деле, поскольку в SpriteKit физическое тело привязано к узлу, мне было интересно, как сделать компонент, который был бы независимым... - person Trevör; 08.09.2016
comment
Да, идея в том, что компоненты никогда не должны зависеть друг от друга, иначе это как бы лишает смысла. Физические тела имеют тенденцию быть разными для каждой уникальной сущности, и существует так много свойств (динамических, затронутыхByGravity), что вам будет намного сложнее превратить их в компонент. - person crashoverride777; 08.09.2016
comment
Давайте продолжим обсуждение в чате. - person Trevör; 08.09.2016
comment
Спасибо за помощь. - person Trevör; 08.09.2016
comment
Добро пожаловать. Я только что обновил ответ более подробно. Удачного кодирования. - person crashoverride777; 08.09.2016