[swift-users] Checking/getting custom objects from a collection
Milos Rankovic
milos at milos-and-slavica.net
Fri Apr 8 05:05:39 CDT 2016
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 at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160408/99fb6061/attachment.html>
More information about the swift-users
mailing list