[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