Это зависит от того, как вы хотите структурировать свои компоненты. Как вы сказали, лучше всего сделать их максимально гибкими, многоразовыми и независимыми друг от друга.
Поэтому я бы просто создал простой компонент рендеринга, как вы хотите. Это то, что я использую в своих играх.
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