[swift-users] Checking/getting custom objects from a collection

Milos Rankovic milos at milos-and-slavica.net
Fri Apr 8 06:12:06 CDT 2016


A type-uniquing alternative (see my previous message):

// Swift 2.2

// Entity-Component System (sketch):
protocol Component {
	static var name: String { get } // not necessary (see comments below)
}

extension Component {
	// can be overridden with `let` by conforming types
	static var name: String { return String(self.dynamicType) }
}

protocol Entity {
	static func with(_: Component...) -> Self
	var components: [String:Component] { get set }
	init()
	func component<T: Component>(_: T.Type) -> T?
}

extension Entity {
	static func with(components: Component...) -> Self {
		var d: [String:Component] = [:]
		for c in components { d[c.dynamicType.name/* String(c.dynamicType) */] = c }
		var entity = self.init()
		entity.components = d
		return entity
	}
	func component<T: Component>(_: T.Type) -> T? {
		return self.components[T.name/* String(T) */] as? T
	}
	// TODO: mutating func add<T: Component>(_: T)
	// TODO: mutating func remove<T: Component>(_: T.Type)
}

// game:
struct Character: Entity {
	var components: [String:Component] = [:]
}

struct Health: Component {
	var percent = 100.0
	var dead: Bool { return percent <= 0 }
}

struct Attack: Component {
	var range = 0, damage = 0
}

// use:
let health = Health()
let attack = Attack()

let character = Character.with(health, attack)

character.component(Health)?.percent // 100

milos

> On 8 Apr 2016, at 11:05, Milos Rankovic via swift-users <swift-users at swift.org> wrote:
> 
> 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 <mailto: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 <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users
> 
> _______________________________________________
> 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/32157049/attachment.html>


More information about the swift-users mailing list