Я пытаюсь создать простой игровой движок для забавных и образовательных целей.У меня есть протокол Game
, который представляет мою игру, и протокол Entity
, который представляет сущность (например, игрок или противник).Наконец, у меня есть протокол EntityComponent
, реализации которого обновляют Entity
.В Swift это выглядит так:
protocol Game {
var entities: [Entity] { get }
}
protocol Entity {
var components: [EntityComponent] { get }
}
protocol EntityComponent {
func update(_ entity: Entity, deltaTime seconds: TimeInterval)
}
Я хочу, чтобы мои компоненты сущности были обобщены с помощью сущностей, которые они обновляют.В Swift я могу использовать associatedtype
:
protocol EntityComponent {
associatedtype EntityType: Entity
func update(_ entity: EntityType, deltaTime seconds: TimeInterval)
}
Однако это приведет к ошибке компиляции для протокола Entity
:
protocol Entity {
var components: [EntityComponent] { get } // ERROR!
}
Протокол 'EntityComponent' можетиспользоваться только в качестве общего ограничения, поскольку оно имеет собственные требования или требования к связанным типам
Эта проблема может быть решена путем определения стирания типа для протокола EntityComponent
и обновления Entity
следующим образом:
protocol Entity {
var components: [AnyEntityComponent<Self>] { get }
}
final class AnyEntityComponent<EntityType: Entity>: EntityComponent {
init<T: EntityComponent>(_ component: T) where T.EntityType == EntityType {
self.update = component.update
}
func update(_ entity: EntityType, deltaTime seconds: TimeInterval) {
update(entity, seconds)
}
private let update: (EntityType, TimeInterval) -> Void
}
К сожалению, это изменение в протоколе Entity
вызывает другую проблему.На этот раз в протоколе Game
:
protocol Game {
var entities: [Entity] { get } // ERROR!
}
Протокол «Сущность» можно использовать только в качестве общего ограничения, поскольку он имеет собственные требования или требования к связанному типу
IЯ не уверен, как это исправить, так как я не могу сделать это путем определения стирания типа (как в случае EntityComponent
).
Буду признателен за любые подсказки и идеи!