This is just a sketch. There may be issues down the line (I’ve indicated some with `TODO`s), but it works and you can try it in the playground:
// Swift 2.2 // utility: extension Array { func first <T> (_: T.Type) -> T? { for e in self where e is T { return e as? T } return nil } } // Entity-Component System (sketch): protocol Component { } protocol Entity { static func with(_: Component...) -> Self // TODO: make get only // also should be a set-by-type really, but that would // force `Component` to be a class (which may be worth it) var components: [Component] { get set } init() func component<T: Component>(_: T.Type) -> T? } extension Entity { static func with(components: Component...) -> Self { var entity = self.init() // TODO: enforce uniquely typed elements entity.components = components return entity } func component<T: Component>(_: T.Type) -> T? { return self.components.first(T) } } // game: struct Character: Entity { // TODO: make private var components: [Component] = [] } struct Health: Component { var percent = 100.0 var dead = false } struct Attack: Component { var range = 0, damage = 0 } // use: var health = Health() var attack = Attack() var character = Character.with(health, attack) character.component(Health)?.percent // 100 Hope this helps, milos > On 8 Apr 2016, at 00:47, Adriano Ferreira via swift-users > <swift-users@swift.org> wrote: > > Hi everyone! > > I’m experimenting with Entity-Component Systems > <https://en.wikipedia.org/wiki/Entity_component_system> and I’d appreciate if > you could help me working on how to check/get custom objects from a > collection. > > The idea is to verify if an entity contains a particular component and, if > so, retrieve it. > > Here’s the API I’d like work on: > > > // Entity Library > class Character: Entity {} > > // Component Library > class HealthComponent: Component { > var health = 100.0 > var isDead = false > } > > class AttackComponent: Component { > var range = 0 > var damage = 0 > } > > // Usage > var healthComponent = HealthComponent() > var attackComponent = AttackComponent() > > var components: [ComponentType] = [healthComponent, attackComponent] > var char = Character(components: components) > > let hc = char.get(component: HealthComponent) > let ac = char.get(component: AttackComponent) > > > So, what are your thoughts on the TODOs below? > > — > > import Foundation > > protocol ComponentType { > var entity: EntityType? { get } > } > > protocol EntityType { > var components: [ComponentType] { get } > func get<T: ComponentType>(component c: T.Type) -> T? > func add(component c: ComponentType) > func remove(component c: ComponentType) > } > > class Component: ComponentType { > var entity: EntityType? > } > > class Entity: EntityType { > var components = [ComponentType]() > > init(components: [ComponentType]) { > for component in components { > self.add(component: component) > } > } > > func get<T: ComponentType>(component c: T.Type) -> T? { > // TODO: - not sure how to work the types here > // if `self` contains component of given type, return it > // otherwise, return nil > } > > func add(component c: ComponentType) { > // TODO: - depends on the `get` function > // if `self` already contains component, just return > // otherwise, self.components += [component] > } > > func remove(component c: ComponentType) { > // TODO: - also depends on the `get` function > // if `self` contains component, remove it > // otherwise, just return > } > } > > > > Best, > > —A > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users