Merge branch 'feature/cleanups' into develop

This commit is contained in:
Christian Treffs 2018-09-27 20:33:23 +02:00
commit 24d9b15b6e
16 changed files with 353 additions and 351 deletions

View File

@ -8,8 +8,8 @@ excluded:
line_length: 220 line_length: 220
number_separator: number_separator:
minimum_length: 5 minimum_length: 5
disabled_rules: #disabled_rules:
- identifier_name #- identifier_name
opt_in_rules: opt_in_rules:
- file_header - file_header
- array_init - array_init

View File

@ -5,12 +5,12 @@
// Created by Christian Treffs on 08.10.17. // Created by Christian Treffs on 08.10.17.
// //
public final class Entity: UniqueEntityIdentifiable { open class Entity: UniqueEntityIdentifiable {
internal(set) public var identifier: EntityIdentifier = EntityIdentifier.invalid internal(set) public var identifier: EntityIdentifier = EntityIdentifier.invalid
public var name: String? public var name: String?
unowned let nexus: Nexus unowned let nexus: Nexus
init(nexus: Nexus, id: EntityIdentifier, name: String? = nil) { internal init(nexus: Nexus, id: EntityIdentifier, name: String? = nil) {
self.nexus = nexus self.nexus = nexus
self.identifier = id self.identifier = id
self.name = name self.name = name

View File

@ -34,11 +34,11 @@ public final class Family: Equatable {
} }
public final var memberIds: UniformEntityIdentifiers { public final var memberIds: UniformEntityIdentifiers {
return nexus?.members(of: traits) ?? UniformEntityIdentifiers() return nexus?.members(withFamilyTraits: traits) ?? UniformEntityIdentifiers()
} }
public final var count: Int { public final var count: Int {
return nexus?.members(of: traits)?.count ?? 0 return nexus?.members(withFamilyTraits: traits)?.count ?? 0
} }
public final func canBecomeMember(_ entity: Entity) -> Bool { public final func canBecomeMember(_ entity: Entity) -> Bool {

View File

@ -8,7 +8,7 @@
public extension Nexus { public extension Nexus {
final var numComponents: Int { final var numComponents: Int {
return componentsByType.reduce(0) { return $0 + $1.value.count } return componentsByType.reduce(0) { $0 + $1.value.count }
} }
final func has(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> Bool { final func has(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> Bool {

View File

@ -29,7 +29,7 @@ extension Nexus {
return entityStorage.count return entityStorage.count
} }
public func has(entity entityId: EntityIdentifier) -> Bool { public func exists(entity entityId: EntityIdentifier) -> Bool {
return entityStorage.contains(entityId.index) return entityStorage.contains(entityId.index)
} }

View File

@ -37,7 +37,7 @@ public extension Nexus {
return family.traits.isMatch(components: componentSet) return family.traits.isMatch(components: componentSet)
} }
func members(of traits: FamilyTraitSet) -> UniformEntityIdentifiers? { func members(withFamilyTraits traits: FamilyTraitSet) -> UniformEntityIdentifiers? {
return familyMembersByTraits[traits] return familyMembersByTraits[traits]
} }
@ -46,11 +46,11 @@ public extension Nexus {
} }
func isMember(_ entityId: EntityIdentifier, in family: Family) -> Bool { func isMember(_ entityId: EntityIdentifier, in family: Family) -> Bool {
return isMember(entityId, in: family.traits) return isMember(entity: entityId, inFamilyWithTraits: family.traits)
} }
func isMember(_ entityId: EntityIdentifier, in traits: FamilyTraitSet) -> Bool { func isMember(entity entityId: EntityIdentifier, inFamilyWithTraits traits: FamilyTraitSet) -> Bool {
guard let members: UniformEntityIdentifiers = members(of: traits) else { guard let members: UniformEntityIdentifiers = members(withFamilyTraits: traits) else {
return false return false
} }
return members.contains(entityId.index) return members.contains(entityId.index)
@ -63,9 +63,8 @@ extension Nexus {
func update(familyMembership entityId: EntityIdentifier) { func update(familyMembership entityId: EntityIdentifier) {
// FIXME: iterating all families is costly for many families // FIXME: iterating all families is costly for many families
for (familyTraits, _) in familyMembersByTraits { familyMembersByTraits.forEach { familyTraits, _ in update(membership: familyTraits, for: entityId) }
update(membership: familyTraits, for: entityId)
}
} }
enum UpdateState { enum UpdateState {
@ -76,32 +75,34 @@ extension Nexus {
case unchanged(id: EntityIdentifier, traits: FamilyTraitSet) case unchanged(id: EntityIdentifier, traits: FamilyTraitSet)
} }
@discardableResult func update(membership traits: FamilyTraitSet, for entityId: EntityIdentifier) {
func update(membership traits: FamilyTraitSet, for entityId: EntityIdentifier) -> UpdateState {
let entityIdx: EntityIndex = entityId.index let entityIdx: EntityIndex = entityId.index
guard let componentIds: SparseComponentIdentifierSet = componentIdsByEntity[entityIdx] else { guard let componentIds: SparseComponentIdentifierSet = componentIdsByEntity[entityIdx] else {
return .noComponents(id: entityId, traits: traits) // no components - so skip
return
} }
let isMember: Bool = self.isMember(entityId, in: traits) let isMember: Bool = self.isMember(entity: entityId, inFamilyWithTraits: traits)
if !has(entity: entityId) && isMember { if !exists(entity: entityId) && isMember {
remove(from: traits, entityId: entityId, entityIdx: entityIdx) remove(entityWithId: entityId, andIndex: entityIdx, fromFamilyWithTraits: traits)
return .removedDeleted(id: entityId, traits: traits) return
} }
// TODO: get rid of set creation for comparison
let componentsSet: ComponentSet = ComponentSet(componentIds) let componentsSet: ComponentSet = ComponentSet(componentIds)
let isMatch: Bool = traits.isMatch(components: componentsSet) let isMatch: Bool = traits.isMatch(components: componentsSet)
switch (isMatch, isMember) { switch (isMatch, isMember) {
case (true, false): case (true, false):
add(to: traits, entityId: entityId, entityIdx: entityIdx) add(entityWithId: entityId, andIndex: entityIdx, toFamilyWithTraits: traits)
notify(FamilyMemberAdded(member: entityId, toFamily: traits)) notify(FamilyMemberAdded(member: entityId, toFamily: traits))
return .added(id: entityId, traits: traits) return
case (false, true): case (false, true):
remove(from: traits, entityId: entityId, entityIdx: entityIdx) remove(entityWithId: entityId, andIndex: entityIdx, fromFamilyWithTraits: traits)
notify(FamilyMemberRemoved(member: entityId, from: traits)) notify(FamilyMemberRemoved(member: entityId, from: traits))
return .removed(id: entityId, traits: traits) return
default: default:
return .unchanged(id: entityId, traits: traits) return
} }
} }
@ -127,28 +128,27 @@ extension Nexus {
// MARK: - fileprivate extensions // MARK: - fileprivate extensions
private extension Nexus { private extension Nexus {
func get(family traits: FamilyTraitSet) -> Family? { final func get(family traits: FamilyTraitSet) -> Family? {
return create(family: traits) return create(family: traits)
} }
func create(family traits: FamilyTraitSet) -> Family { final func create(family traits: FamilyTraitSet) -> Family {
let family: Family = Family(self, traits: traits) let family: Family = Family(self, traits: traits)
return family return family
} }
func calculateTraitEntityIdHash(traitHash: FamilyTraitSetHash, entityIdx: EntityIndex) -> TraitEntityIdHash { final func calculateTraitEntityIdHash(traitHash: FamilyTraitSetHash, entityIdx: EntityIndex) -> TraitEntityIdHash {
return hash(combine: traitHash, entityIdx) return hash(combine: traitHash, entityIdx)
} }
func add(to traits: FamilyTraitSet, entityId: EntityIdentifier, entityIdx: EntityIndex) { final func add(entityWithId entityId: EntityIdentifier, andIndex entityIdx: EntityIndex, toFamilyWithTraits traits: FamilyTraitSet) {
if familyMembersByTraits[traits] == nil { if familyMembersByTraits[traits] == nil {
familyMembersByTraits[traits] = UniformEntityIdentifiers() familyMembersByTraits[traits] = UniformEntityIdentifiers()
} }
familyMembersByTraits[traits]?.insert(entityId, at: entityIdx) familyMembersByTraits[traits]?.insert(entityId, at: entityIdx)
} }
func remove(from traits: FamilyTraitSet, entityId: EntityIdentifier, entityIdx: EntityIndex) { final func remove(entityWithId entityId: EntityIdentifier, andIndex entityIdx: EntityIndex, fromFamilyWithTraits traits: FamilyTraitSet) {
familyMembersByTraits[traits]?.remove(at: entityIdx) familyMembersByTraits[traits]?.remove(at: entityIdx)
} }
} }

View File

@ -5,7 +5,7 @@
// Created by Christian Treffs on 30.10.17. // Created by Christian Treffs on 30.10.17.
// //
public class UnorderedSparseSet<Element>: Sequence { public class UnorderedSparseSet<Element> {
public typealias Index = Int public typealias Index = Int
public typealias Key = Int public typealias Key = Int
@ -136,6 +136,33 @@ public class UnorderedSparseSet<Element>: Sequence {
} }
} }
extension UnorderedSparseSet: MutableCollection, RandomAccessCollection {
public func index(after index: Index) -> Int {
return dense.index(after: index)
}
public subscript(position: Index) -> Element {
get {
guard let element: Element = get(at: position) else {
fatalError("no element at index \(position)")
}
return element
}
set(newValue) {
insert(newValue, at: position)
}
}
public var startIndex: Index {
return dense.startIndex
}
public var endIndex: Index {
return dense.endIndex
}
}
extension UnorderedSparseSet.Entry: Equatable where UnorderedSparseSet.Element: Equatable { extension UnorderedSparseSet.Entry: Equatable where UnorderedSparseSet.Element: Equatable {
public static func == (lhs: UnorderedSparseSet.Entry, rhs: UnorderedSparseSet.Entry) -> Bool { public static func == (lhs: UnorderedSparseSet.Entry, rhs: UnorderedSparseSet.Entry) -> Bool {
return lhs.element == rhs.element && lhs.key == rhs.key return lhs.element == rhs.element && lhs.key == rhs.key

View File

@ -57,9 +57,8 @@ class ExampleSystem {
position.x *= 2 position.x *= 2
velocity.a *= 2 velocity.a *= 2
} }
} }
} }

View File

@ -5,79 +5,78 @@
// Created by Christian Treffs on 09.05.18. // Created by Christian Treffs on 09.05.18.
// //
import XCTest
import FirebladeECS import FirebladeECS
import XCTest
class FamilyPerformanceTests: XCTestCase { class FamilyPerformanceTests: XCTestCase {
var nexus: Nexus! var nexus: Nexus!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
nexus = Nexus() nexus = Nexus()
} }
override func tearDown() { override func tearDown() {
nexus = nil nexus = nil
super.tearDown() super.tearDown()
} }
func testMeasureIterateMembers() { func testMeasureIterateMembers() {
let number: Int = 10_000 let number: Int = 10_000
for i in 0..<number { for i in 0..<number {
nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent()) nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent())
} }
let family = nexus.family(requiresAll: [Position.self, Velocity.self], let family = nexus.family(requiresAll: [Position.self, Velocity.self],
excludesAll: [Party.self], excludesAll: [Party.self],
needsAtLeastOne: [Name.self, EmptyComponent.self]) needsAtLeastOne: [Name.self, EmptyComponent.self])
XCTAssertEqual(family.count, number) XCTAssertEqual(family.count, number)
XCTAssertEqual(nexus.numEntities, number) XCTAssertEqual(nexus.numEntities, number)
measure { measure {
family.iterate { (entityId: EntityIdentifier) in family.iterate { (entityId: EntityIdentifier) in
_ = entityId _ = entityId
} }
} }
} }
func testMeasureFamilyIterationOne() { func testMeasureFamilyIterationOne() {
let number: Int = 10_000 let number: Int = 10_000
for i in 0..<number { for i in 0..<number {
nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent()) nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent())
} }
let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self]) let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self])
XCTAssert(family.count == number) XCTAssert(family.count == number)
XCTAssert(nexus.numEntities == number) XCTAssert(nexus.numEntities == number)
measure { measure {
family.iterate { (velocity: Velocity!) in family.iterate { (velocity: Velocity!) in
_ = velocity _ = velocity
} }
} }
} }
func testMeasureFamilyIterationThree() { func testMeasureFamilyIterationThree() {
let number: Int = 10_000 let number: Int = 10_000
for i in 0..<number { for i in 0..<number {
nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent()) nexus.create(entity: "\(i)").assign(Position(x: 1 + i, y: 2 + i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent())
} }
let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self]) let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self])
XCTAssert(family.count == number) XCTAssert(family.count == number)
XCTAssert(nexus.numEntities == number) XCTAssert(nexus.numEntities == number)
measure { measure {
family.iterate { (entity: Entity!, position: Position!, velocity: Velocity!, name: Name?) in family.iterate { (entity: Entity!, position: Position!, velocity: Velocity!, name: Name?) in
position.x += entity.identifier.index position.x += entity.identifier.index
@ -85,9 +84,7 @@ class FamilyPerformanceTests: XCTestCase {
_ = name _ = name
} }
} }
} }
} }

View File

@ -9,173 +9,171 @@
import XCTest import XCTest
class FamilyTests: XCTestCase { class FamilyTests: XCTestCase {
var nexus: Nexus! var nexus: Nexus!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
nexus = Nexus() nexus = Nexus()
} }
override func tearDown() { override func tearDown() {
nexus = nil nexus = nil
super.tearDown() super.tearDown()
} }
func testFamilyCreation() { func testFamilyCreation() {
let family: Family = nexus.family(requiresAll: [Position.self], let family: Family = nexus.family(requiresAll: [Position.self],
excludesAll: [Name.self], excludesAll: [Name.self],
needsAtLeastOne: [Velocity.self]) needsAtLeastOne: [Velocity.self])
XCTAssertEqual(family.nexus, self.nexus) XCTAssertEqual(family.nexus, self.nexus)
XCTAssertTrue(family.nexus === self.nexus) XCTAssertTrue(family.nexus === self.nexus)
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
XCTAssertEqual(nexus.familyMembersByTraits.values.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.values.count, 1)
let traits = FamilyTraitSet(requiresAll: [Position.self], excludesAll: [Name.self], needsAtLeastOne: [Velocity.self]) let traits = FamilyTraitSet(requiresAll: [Position.self], excludesAll: [Name.self], needsAtLeastOne: [Velocity.self])
XCTAssertEqual(family.traits, traits) XCTAssertEqual(family.traits, traits)
} }
func testFamilyReuse() { func testFamilyReuse() {
let familyA: Family = nexus.family(requiresAll: [Position.self], let familyA: Family = nexus.family(requiresAll: [Position.self],
excludesAll: [Name.self], excludesAll: [Name.self],
needsAtLeastOne: [Velocity.self]) needsAtLeastOne: [Velocity.self])
let familyB: Family = nexus.family(requiresAll: [Position.self], let familyB: Family = nexus.family(requiresAll: [Position.self],
excludesAll: [Name.self], excludesAll: [Name.self],
needsAtLeastOne: [Velocity.self]) needsAtLeastOne: [Velocity.self])
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
XCTAssertEqual(nexus.familyMembersByTraits.values.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.values.count, 1)
XCTAssertEqual(familyA, familyB) XCTAssertEqual(familyA, familyB)
} }
func testFamilyAbandoned() { func testFamilyAbandoned() {
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 0) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 0)
_ = nexus.family(requiresAll: [Position.self], excludesAll: []) _ = nexus.family(requiresAll: [Position.self], excludesAll: [])
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
let entity = nexus.create(entity: "eimer") let entity = nexus.create(entity: "eimer")
entity.assign(Position(x: 1, y: 1)) entity.assign(Position(x: 1, y: 1))
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
entity.remove(Position.self) entity.remove(Position.self)
// FIXME: the family trait should vanish when no entity with revlevant component is present anymore // FIXME: the family trait should vanish when no entity with revlevant component is present anymore
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
nexus.destroy(entity: entity) nexus.destroy(entity: entity)
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
} }
func testFamilyLateMember() { func testFamilyLateMember() {
let eEarly = nexus.create(entity: "eary").assign(Position(x: 1, y: 2)) let eEarly = nexus.create(entity: "eary").assign(Position(x: 1, y: 2))
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 0) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 0)
let family = nexus.family(requiresAll: [Position.self], let family = nexus.family(requiresAll: [Position.self],
excludesAll: []) excludesAll: [])
XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1) XCTAssertEqual(nexus.familyMembersByTraits.keys.count, 1)
let eLate = nexus.create(entity: "late").assign(Position(x: 1, y: 2)) let eLate = nexus.create(entity: "late").assign(Position(x: 1, y: 2))
XCTAssertTrue(family.isMember(eEarly)) XCTAssertTrue(family.isMember(eEarly))
XCTAssertTrue(family.isMember(eLate)) XCTAssertTrue(family.isMember(eLate))
} }
func testFamilyExchange() { func testFamilyExchange() {
let number: Int = 10 let number: Int = 10
for i in 0..<number { for i in 0..<number {
nexus.create(entity: "\(i)").assign(Position(x: i + 1, y: i + 2)) nexus.create(entity: "\(i)").assign(Position(x: i + 1, y: i + 2))
} }
let familyA = nexus.family(requiresAll: [Position.self], let familyA = nexus.family(requiresAll: [Position.self],
excludesAll: [Velocity.self]) excludesAll: [Velocity.self])
let familyB = nexus.family(requiresAll: [Velocity.self], let familyB = nexus.family(requiresAll: [Velocity.self],
excludesAll: [Position.self]) excludesAll: [Position.self])
XCTAssertEqual(familyA.count, 10) XCTAssertEqual(familyA.count, 10)
XCTAssertEqual(familyB.count, 0) XCTAssertEqual(familyB.count, 0)
familyA.iterate { (entity: Entity!) in familyA.iterate { (entity: Entity!) in
entity.assign(Velocity(a: 3.14)) entity.assign(Velocity(a: 3.14))
entity.remove(Position.self) entity.remove(Position.self)
} }
XCTAssertEqual(familyA.count, 0) XCTAssertEqual(familyA.count, 0)
XCTAssertEqual(familyB.count, 10) XCTAssertEqual(familyB.count, 10)
familyB.iterate { (entity: Entity!, velocity: Velocity!) in familyB.iterate { (entity: Entity!, velocity: Velocity!) in
entity.assign(Position(x: 1, y: 2)) entity.assign(Position(x: 1, y: 2))
entity.remove(velocity) entity.remove(velocity)
} }
XCTAssertEqual(familyA.count, 10) XCTAssertEqual(familyA.count, 10)
XCTAssertEqual(familyB.count, 0) XCTAssertEqual(familyB.count, 0)
} }
func testFamilyMemberBasicIteration() { func testFamilyMemberBasicIteration() {
for i in 0..<1000 { for i in 0..<1000 {
nexus.create(entity: "\(i)").assign(Position(x: i + 1, y: i + 2)) nexus.create(entity: "\(i)").assign(Position(x: i + 1, y: i + 2))
nexus.create(entity: "\(i)").assign(Velocity(a: Float(i))) nexus.create(entity: "\(i)").assign(Velocity(a: Float(i)))
} }
let familyA = nexus.family(requiresAll: [Position.self], let familyA = nexus.family(requiresAll: [Position.self],
excludesAll: [Velocity.self]) excludesAll: [Velocity.self])
let familyB = nexus.family(requiresAll: [Velocity.self], let familyB = nexus.family(requiresAll: [Velocity.self],
excludesAll: [Position.self]) excludesAll: [Position.self])
familyA.iterate { (pos: Position?, vel: Velocity?) in familyA.iterate { (pos: Position?, vel: Velocity?) in
XCTAssertNotNil(pos) XCTAssertNotNil(pos)
XCTAssertNil(vel) XCTAssertNil(vel)
} }
familyB.iterate { (pos: Position?, vel: Velocity?) in familyB.iterate { (pos: Position?, vel: Velocity?) in
XCTAssertNil(pos) XCTAssertNil(pos)
XCTAssertNotNil(vel) XCTAssertNotNil(vel)
} }
} }
func createDefaultEntity(name: String?) { func createDefaultEntity(name: String?) {
let e = nexus.create(entity: name) let e = nexus.create(entity: name)
e.assign(Position(x: 1, y: 2)) e.assign(Position(x: 1, y: 2))
e.assign(Color()) e.assign(Color())
} }
func testFamilyBulkDestroy() { func testFamilyBulkDestroy() {
let count = 10_000 let count = 10_000
for _ in 0..<count { for _ in 0..<count {
createDefaultEntity(name: nil) createDefaultEntity(name: nil)
} }
let family = nexus.family(requiresAll: [Position.self], excludesAll: []) let family = nexus.family(requiresAll: [Position.self], excludesAll: [])
XCTAssertEqual(family.memberIds.count, count) XCTAssertEqual(family.memberIds.count, count)
var currentCount: Int = (count / 2) var currentCount: Int = (count / 2)
family.iterate { (entity: Entity!) in family.iterate { (entity: Entity!) in
if currentCount > 0 { if currentCount > 0 {
entity.destroy() entity.destroy()
@ -185,14 +183,14 @@ class FamilyTests: XCTestCase {
return return
} }
} }
XCTAssertEqual(family.memberIds.count, (count / 2)) XCTAssertEqual(family.memberIds.count, (count / 2))
for _ in 0..<count { for _ in 0..<count {
createDefaultEntity(name: nil) createDefaultEntity(name: nil)
} }
XCTAssertEqual(family.memberIds.count, count + (count / 2)) XCTAssertEqual(family.memberIds.count, count + (count / 2))
} }
} }

View File

@ -5,70 +5,69 @@
// Created by Christian Treffs on 09.05.18. // Created by Christian Treffs on 09.05.18.
// //
import XCTest
@testable import FirebladeECS @testable import FirebladeECS
import XCTest
class FamilyTraitsTests: XCTestCase { class FamilyTraitsTests: XCTestCase {
var nexus: Nexus! var nexus: Nexus!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
nexus = Nexus() nexus = Nexus()
} }
override func tearDown() { override func tearDown() {
nexus = nil nexus = nil
super.tearDown() super.tearDown()
} }
func testTraitCommutativity() { func testTraitCommutativity() {
let t1 = FamilyTraitSet(requiresAll: [Position.self, Velocity.self], let t1 = FamilyTraitSet(requiresAll: [Position.self, Velocity.self],
excludesAll: [Name.self], excludesAll: [Name.self],
needsAtLeastOne: []) needsAtLeastOne: [])
let t2 = FamilyTraitSet(requiresAll: [Velocity.self, Position.self], let t2 = FamilyTraitSet(requiresAll: [Velocity.self, Position.self],
excludesAll: [Name.self], excludesAll: [Name.self],
needsAtLeastOne: []) needsAtLeastOne: [])
XCTAssertEqual(t1, t2) XCTAssertEqual(t1, t2)
XCTAssertEqual(t1.hashValue, t2.hashValue) XCTAssertEqual(t1.hashValue, t2.hashValue)
} }
func testTraitMatching() { func testTraitMatching() {
let a = nexus.create(entity: "a") let a = nexus.create(entity: "a")
a.assign(Position(x: 1, y: 2)) a.assign(Position(x: 1, y: 2))
a.assign(Name(name: "myName")) a.assign(Name(name: "myName"))
a.assign(Velocity(a: 3.14)) a.assign(Velocity(a: 3.14))
a.assign(EmptyComponent()) a.assign(EmptyComponent())
let noMatch = nexus.family(requiresAll: [Position.self, Velocity.self], let noMatch = nexus.family(requiresAll: [Position.self, Velocity.self],
excludesAll: [Name.self]) excludesAll: [Name.self])
let isMatch = nexus.family(requiresAll: [Position.self, Velocity.self], let isMatch = nexus.family(requiresAll: [Position.self, Velocity.self],
excludesAll: [], excludesAll: [],
needsAtLeastOne: [Name.self, EmptyComponent.self]) needsAtLeastOne: [Name.self, EmptyComponent.self])
XCTAssertFalse(noMatch.canBecomeMember(a)) XCTAssertFalse(noMatch.canBecomeMember(a))
XCTAssertTrue(isMatch.canBecomeMember(a)) XCTAssertTrue(isMatch.canBecomeMember(a))
} }
func testMeasureTraitMatching() { func testMeasureTraitMatching() {
let a = nexus.create(entity: "a") let a = nexus.create(entity: "a")
a.assign(Position(x: 1, y: 2)) a.assign(Position(x: 1, y: 2))
a.assign(Name(name: "myName")) a.assign(Name(name: "myName"))
a.assign(Velocity(a: 3.14)) a.assign(Velocity(a: 3.14))
a.assign(EmptyComponent()) a.assign(EmptyComponent())
let isMatch = nexus.family(requiresAll: [Position.self, Velocity.self], let isMatch = nexus.family(requiresAll: [Position.self, Velocity.self],
excludesAll: [Party.self], excludesAll: [Party.self],
needsAtLeastOne: [Name.self, EmptyComponent.self]) needsAtLeastOne: [Name.self, EmptyComponent.self])
measure { measure {
for _ in 0..<10_000 { for _ in 0..<10_000 {
let success = isMatch.canBecomeMember(a) let success = isMatch.canBecomeMember(a)
@ -76,5 +75,5 @@ class FamilyTraitsTests: XCTestCase {
} }
} }
} }
} }

View File

@ -39,9 +39,9 @@ class HashingTests: XCTestCase {
} }
func testMeasureCombineHash() { func testMeasureCombineHash() {
let a: Set<Int> = Set<Int>.init([14_561_291, 26_451_562, 34_562_182, 488_972_556, 5_128_426_962, 68_211_812]) let a: Set<Int> = Set<Int>([14_561_291, 26_451_562, 34_562_182, 488_972_556, 5_128_426_962, 68_211_812])
let b: Set<Int> = Set<Int>.init([1_083_838, 912_312, 83_333, 71_234_555, 4_343_234]) let b: Set<Int> = Set<Int>([1_083_838, 912_312, 83_333, 71_234_555, 4_343_234])
let c: Set<Int> = Set<Int>.init([3_410_346_899_765, 90_000_002, 12_212_321, 71, 6_123_345_676_543]) let c: Set<Int> = Set<Int>([3_410_346_899_765, 90_000_002, 12_212_321, 71, 6_123_345_676_543])
let input: ContiguousArray<Int> = ContiguousArray<Int>(arrayLiteral: a.hashValue, b.hashValue, c.hashValue) let input: ContiguousArray<Int> = ContiguousArray<Int>(arrayLiteral: a.hashValue, b.hashValue, c.hashValue)
measure { measure {
@ -53,9 +53,9 @@ class HashingTests: XCTestCase {
} }
func testMeasureSetOfSetHash() { func testMeasureSetOfSetHash() {
let a: Set<Int> = Set<Int>.init([14_561_291, 26_451_562, 34_562_182, 488_972_556, 5_128_426_962, 68_211_812]) let a: Set<Int> = Set<Int>([14_561_291, 26_451_562, 34_562_182, 488_972_556, 5_128_426_962, 68_211_812])
let b: Set<Int> = Set<Int>.init([1_083_838, 912_312, 83_333, 71_234_555, 4_343_234]) let b: Set<Int> = Set<Int>([1_083_838, 912_312, 83_333, 71_234_555, 4_343_234])
let c: Set<Int> = Set<Int>.init([3_410_346_899_765, 90_000_002, 12_212_321, 71, 6_123_345_676_543]) let c: Set<Int> = Set<Int>([3_410_346_899_765, 90_000_002, 12_212_321, 71, 6_123_345_676_543])
let input = Set<Set<Int>>(arrayLiteral: a, b, c) let input = Set<Set<Int>>(arrayLiteral: a, b, c)
measure { measure {

View File

@ -11,7 +11,7 @@ import XCTest
class NexusTests: XCTestCase { class NexusTests: XCTestCase {
var nexus: Nexus! var nexus: Nexus!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
nexus = Nexus() nexus = Nexus()
@ -26,44 +26,43 @@ class NexusTests: XCTestCase {
XCTAssertEqual(nexus.numEntities, 0) XCTAssertEqual(nexus.numEntities, 0)
let e0 = nexus.create() let e0 = nexus.create()
XCTAssertEqual(e0.identifier.index, 0) XCTAssertEqual(e0.identifier.index, 0)
XCTAssertEqual(nexus.numEntities, 1) XCTAssertEqual(nexus.numEntities, 1)
let e1 = nexus.create(entity: "Entity 1") let e1 = nexus.create(entity: "Entity 1")
XCTAssert(e1.identifier.index == 1) XCTAssert(e1.identifier.index == 1)
XCTAssert(nexus.numEntities == 2) XCTAssert(nexus.numEntities == 2)
XCTAssertNil(e0.name) XCTAssertNil(e0.name)
XCTAssertEqual(e1.name, "Entity 1") XCTAssertEqual(e1.name, "Entity 1")
} }
func testEntityDestroy() { func testEntityDestroy() {
testEntityCreate() testEntityCreate()
XCTAssertEqual(nexus.numEntities, 2) XCTAssertEqual(nexus.numEntities, 2)
let e1: Entity = nexus.get(entity: 1)! let e1: Entity = nexus.get(entity: 1)!
XCTAssertEqual(e1.identifier.index, 1) XCTAssertEqual(e1.identifier.index, 1)
XCTAssertTrue(nexus.destroy(entity: e1)) XCTAssertTrue(nexus.destroy(entity: e1))
XCTAssertFalse(nexus.destroy(entity: e1)) XCTAssertFalse(nexus.destroy(entity: e1))
XCTAssertEqual(nexus.numEntities, 1) XCTAssertEqual(nexus.numEntities, 1)
let e1Again: Entity? = nexus.get(entity: 1) let e1Again: Entity? = nexus.get(entity: 1)
XCTAssertNil(e1Again) XCTAssertNil(e1Again)
XCTAssertEqual(nexus.numEntities, 1) XCTAssertEqual(nexus.numEntities, 1)
nexus.clear() nexus.clear()
XCTAssertEqual(nexus.numEntities, 0) XCTAssertEqual(nexus.numEntities, 0)
} }
func testComponentCreation() { func testComponentCreation() {
XCTAssert(nexus.numEntities == 0) XCTAssert(nexus.numEntities == 0)
let e0: Entity = nexus.create(entity: "e0") let e0: Entity = nexus.create(entity: "e0")
@ -82,7 +81,7 @@ class NexusTests: XCTestCase {
} }
func testComponentDeletion() { func testComponentDeletion() {
let identifier: EntityIdentifier = nexus.create(entity: "e0").identifier let identifier: EntityIdentifier = nexus.create(entity: "e0").identifier
let e0 = nexus.get(entity: identifier)! let e0 = nexus.get(entity: identifier)!

View File

@ -9,28 +9,28 @@
import XCTest import XCTest
class SparseSetTests: XCTestCase { class SparseSetTests: XCTestCase {
var set: UnorderedSparseSet<Position>! var set: UnorderedSparseSet<Position>!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
set = UnorderedSparseSet<Position>() set = UnorderedSparseSet<Position>()
} }
override func tearDown() { override func tearDown() {
set = nil set = nil
super.tearDown() super.tearDown()
} }
func testSparseSetAdd() { func testSparseSetAdd() {
let num: Int = 100 let num: Int = 100
for idx in 0..<num { for idx in 0..<num {
let pos = Position(x: idx, y: idx) let pos = Position(x: idx, y: idx)
set.insert(pos, at: idx) set.insert(pos, at: idx)
} }
XCTAssertEqual(set.count, num) XCTAssertEqual(set.count, num)
XCTAssertEqual(set.get(at: 0)?.x, 0) XCTAssertEqual(set.get(at: 0)?.x, 0)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
@ -45,54 +45,54 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 99)?.x, 99) XCTAssertEqual(set.get(at: 99)?.x, 99)
XCTAssertEqual(set.get(at: 100)?.x, nil) XCTAssertEqual(set.get(at: 100)?.x, nil)
} }
func testSparseSetAddAndReplace() { func testSparseSetAddAndReplace() {
let p1 = Position(x: 1, y: 1) let p1 = Position(x: 1, y: 1)
let p2 = Position(x: 2, y: 2) let p2 = Position(x: 2, y: 2)
XCTAssertTrue(set.insert(p1, at: 10)) XCTAssertTrue(set.insert(p1, at: 10))
XCTAssertEqual(set.get(at: 10)?.x, p1.x) XCTAssertEqual(set.get(at: 10)?.x, p1.x)
XCTAssertEqual(set.count, 1) XCTAssertEqual(set.count, 1)
XCTAssertFalse(set.insert(p2, at: 10)) XCTAssertFalse(set.insert(p2, at: 10))
XCTAssertEqual(set.get(at: 10)?.x, p2.x) XCTAssertEqual(set.get(at: 10)?.x, p2.x)
XCTAssertEqual(set.count, 1) XCTAssertEqual(set.count, 1)
} }
func testSparseSetGet() { func testSparseSetGet() {
let p1 = Position(x: 1, y: 1) let p1 = Position(x: 1, y: 1)
set.insert(p1, at: 10) set.insert(p1, at: 10)
XCTAssertEqual(set.get(at: 10)?.x, p1.x) XCTAssertEqual(set.get(at: 10)?.x, p1.x)
XCTAssertNil(set.get(at: 33)) XCTAssertNil(set.get(at: 33))
XCTAssertNotNil(set.remove(at: 10)) XCTAssertNotNil(set.remove(at: 10))
XCTAssertNil(set.get(at: 10)) XCTAssertNil(set.get(at: 10))
} }
func testSparseSetRemove() { func testSparseSetRemove() {
let num: Int = 7 let num: Int = 7
for idx in 0..<num { for idx in 0..<num {
let pos = Position(x: idx, y: idx) let pos = Position(x: idx, y: idx)
set.insert(pos, at: idx) set.insert(pos, at: idx)
XCTAssertEqual(set.sparse[idx], idx) XCTAssertEqual(set.sparse[idx], idx)
XCTAssertEqual(set.dense.count, idx+1) XCTAssertEqual(set.dense.count, idx + 1)
} }
XCTAssertEqual(set.count, num) XCTAssertEqual(set.count, num)
XCTAssertEqual(set.sparse.count, num) XCTAssertEqual(set.sparse.count, num)
XCTAssertEqual(set.dense.count, num) XCTAssertEqual(set.dense.count, num)
XCTAssertEqual(set.get(at: 0)?.x, 0) XCTAssertEqual(set.get(at: 0)?.x, 0)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
XCTAssertEqual(set.get(at: 2)?.x, 2) XCTAssertEqual(set.get(at: 2)?.x, 2)
@ -101,7 +101,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, 6) XCTAssertEqual(set.get(at: 6)?.x, 6)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertTrue(set.contains(0)) XCTAssertTrue(set.contains(0))
XCTAssertTrue(set.contains(1)) XCTAssertTrue(set.contains(1))
XCTAssertTrue(set.contains(2)) XCTAssertTrue(set.contains(2))
@ -110,7 +110,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertTrue(set.contains(6)) XCTAssertTrue(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], 0) XCTAssertEqual(set.sparse[0], 0)
XCTAssertEqual(set.sparse[1], 1) XCTAssertEqual(set.sparse[1], 1)
XCTAssertEqual(set.sparse[2], 2) XCTAssertEqual(set.sparse[2], 2)
@ -119,16 +119,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 5) XCTAssertEqual(set.sparse[5], 5)
XCTAssertEqual(set.sparse[6], 6) XCTAssertEqual(set.sparse[6], 6)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 3) set.remove(at: 3)
XCTAssertEqual(set.count, num-1) XCTAssertEqual(set.count, num - 1)
XCTAssertEqual(set.sparse.count, num-1) XCTAssertEqual(set.sparse.count, num - 1)
XCTAssertEqual(set.dense.count, num-1) XCTAssertEqual(set.dense.count, num - 1)
XCTAssertEqual(set.get(at: 0)?.x, 0) XCTAssertEqual(set.get(at: 0)?.x, 0)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
XCTAssertEqual(set.get(at: 2)?.x, 2) XCTAssertEqual(set.get(at: 2)?.x, 2)
@ -137,7 +135,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, 6) XCTAssertEqual(set.get(at: 6)?.x, 6)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertTrue(set.contains(0)) XCTAssertTrue(set.contains(0))
XCTAssertTrue(set.contains(1)) XCTAssertTrue(set.contains(1))
XCTAssertTrue(set.contains(2)) XCTAssertTrue(set.contains(2))
@ -146,7 +144,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertTrue(set.contains(6)) XCTAssertTrue(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], 0) XCTAssertEqual(set.sparse[0], 0)
XCTAssertEqual(set.sparse[1], 1) XCTAssertEqual(set.sparse[1], 1)
XCTAssertEqual(set.sparse[2], 2) XCTAssertEqual(set.sparse[2], 2)
@ -155,17 +153,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 5) XCTAssertEqual(set.sparse[5], 5)
XCTAssertEqual(set.sparse[6], 3) XCTAssertEqual(set.sparse[6], 3)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 2) set.remove(at: 2)
XCTAssertEqual(set.count, num-2) XCTAssertEqual(set.count, num - 2)
XCTAssertEqual(set.sparse.count, num-2) XCTAssertEqual(set.sparse.count, num - 2)
XCTAssertEqual(set.dense.count, num-2) XCTAssertEqual(set.dense.count, num - 2)
XCTAssertEqual(set.get(at: 0)?.x, 0) XCTAssertEqual(set.get(at: 0)?.x, 0)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -174,7 +169,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, 6) XCTAssertEqual(set.get(at: 6)?.x, 6)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertTrue(set.contains(0)) XCTAssertTrue(set.contains(0))
XCTAssertTrue(set.contains(1)) XCTAssertTrue(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -183,7 +178,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertTrue(set.contains(6)) XCTAssertTrue(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], 0) XCTAssertEqual(set.sparse[0], 0)
XCTAssertEqual(set.sparse[1], 1) XCTAssertEqual(set.sparse[1], 1)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -192,17 +187,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 2) XCTAssertEqual(set.sparse[5], 2)
XCTAssertEqual(set.sparse[6], 3) XCTAssertEqual(set.sparse[6], 3)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 0) set.remove(at: 0)
XCTAssertEqual(set.count, num-3) XCTAssertEqual(set.count, num - 3)
XCTAssertEqual(set.sparse.count, num-3) XCTAssertEqual(set.sparse.count, num - 3)
XCTAssertEqual(set.dense.count, num-3) XCTAssertEqual(set.dense.count, num - 3)
XCTAssertEqual(set.get(at: 0)?.x, nil) XCTAssertEqual(set.get(at: 0)?.x, nil)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -211,7 +203,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, 6) XCTAssertEqual(set.get(at: 6)?.x, 6)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertFalse(set.contains(0)) XCTAssertFalse(set.contains(0))
XCTAssertTrue(set.contains(1)) XCTAssertTrue(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -220,7 +212,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertTrue(set.contains(6)) XCTAssertTrue(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], nil) XCTAssertEqual(set.sparse[0], nil)
XCTAssertEqual(set.sparse[1], 1) XCTAssertEqual(set.sparse[1], 1)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -229,16 +221,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 2) XCTAssertEqual(set.sparse[5], 2)
XCTAssertEqual(set.sparse[6], 3) XCTAssertEqual(set.sparse[6], 3)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 1) set.remove(at: 1)
XCTAssertEqual(set.count, num-4) XCTAssertEqual(set.count, num - 4)
XCTAssertEqual(set.sparse.count, num-4) XCTAssertEqual(set.sparse.count, num - 4)
XCTAssertEqual(set.dense.count, num-4) XCTAssertEqual(set.dense.count, num - 4)
XCTAssertEqual(set.get(at: 0)?.x, nil) XCTAssertEqual(set.get(at: 0)?.x, nil)
XCTAssertEqual(set.get(at: 1)?.x, nil) XCTAssertEqual(set.get(at: 1)?.x, nil)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -247,7 +237,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, 6) XCTAssertEqual(set.get(at: 6)?.x, 6)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertFalse(set.contains(0)) XCTAssertFalse(set.contains(0))
XCTAssertFalse(set.contains(1)) XCTAssertFalse(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -256,7 +246,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertTrue(set.contains(6)) XCTAssertTrue(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], nil) XCTAssertEqual(set.sparse[0], nil)
XCTAssertEqual(set.sparse[1], nil) XCTAssertEqual(set.sparse[1], nil)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -265,14 +255,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 2) XCTAssertEqual(set.sparse[5], 2)
XCTAssertEqual(set.sparse[6], 1) XCTAssertEqual(set.sparse[6], 1)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 6) set.remove(at: 6)
XCTAssertEqual(set.count, num-5) XCTAssertEqual(set.count, num - 5)
XCTAssertEqual(set.sparse.count, num-5) XCTAssertEqual(set.sparse.count, num - 5)
XCTAssertEqual(set.dense.count, num-5) XCTAssertEqual(set.dense.count, num - 5)
XCTAssertEqual(set.get(at: 0)?.x, nil) XCTAssertEqual(set.get(at: 0)?.x, nil)
XCTAssertEqual(set.get(at: 1)?.x, nil) XCTAssertEqual(set.get(at: 1)?.x, nil)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -281,7 +271,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, 5) XCTAssertEqual(set.get(at: 5)?.x, 5)
XCTAssertEqual(set.get(at: 6)?.x, nil) XCTAssertEqual(set.get(at: 6)?.x, nil)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertFalse(set.contains(0)) XCTAssertFalse(set.contains(0))
XCTAssertFalse(set.contains(1)) XCTAssertFalse(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -290,7 +280,7 @@ class SparseSetTests: XCTestCase {
XCTAssertTrue(set.contains(5)) XCTAssertTrue(set.contains(5))
XCTAssertFalse(set.contains(6)) XCTAssertFalse(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], nil) XCTAssertEqual(set.sparse[0], nil)
XCTAssertEqual(set.sparse[1], nil) XCTAssertEqual(set.sparse[1], nil)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -299,14 +289,14 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], 1) XCTAssertEqual(set.sparse[5], 1)
XCTAssertEqual(set.sparse[6], nil) XCTAssertEqual(set.sparse[6], nil)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 5) set.remove(at: 5)
XCTAssertEqual(set.count, num-6) XCTAssertEqual(set.count, num - 6)
XCTAssertEqual(set.sparse.count, num-6) XCTAssertEqual(set.sparse.count, num - 6)
XCTAssertEqual(set.dense.count, num-6) XCTAssertEqual(set.dense.count, num - 6)
XCTAssertEqual(set.get(at: 0)?.x, nil) XCTAssertEqual(set.get(at: 0)?.x, nil)
XCTAssertEqual(set.get(at: 1)?.x, nil) XCTAssertEqual(set.get(at: 1)?.x, nil)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -315,7 +305,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, nil) XCTAssertEqual(set.get(at: 5)?.x, nil)
XCTAssertEqual(set.get(at: 6)?.x, nil) XCTAssertEqual(set.get(at: 6)?.x, nil)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertFalse(set.contains(0)) XCTAssertFalse(set.contains(0))
XCTAssertFalse(set.contains(1)) XCTAssertFalse(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -324,7 +314,7 @@ class SparseSetTests: XCTestCase {
XCTAssertFalse(set.contains(5)) XCTAssertFalse(set.contains(5))
XCTAssertFalse(set.contains(6)) XCTAssertFalse(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], nil) XCTAssertEqual(set.sparse[0], nil)
XCTAssertEqual(set.sparse[1], nil) XCTAssertEqual(set.sparse[1], nil)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -333,15 +323,15 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], nil) XCTAssertEqual(set.sparse[5], nil)
XCTAssertEqual(set.sparse[6], nil) XCTAssertEqual(set.sparse[6], nil)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
// --------------------------------------------- // ---------------------------------------------
set.remove(at: 4) set.remove(at: 4)
XCTAssertEqual(set.count, 0) XCTAssertEqual(set.count, 0)
XCTAssertEqual(set.sparse.count, 0) XCTAssertEqual(set.sparse.count, 0)
XCTAssertEqual(set.dense.count, 0) XCTAssertEqual(set.dense.count, 0)
XCTAssertTrue(set.isEmpty) XCTAssertTrue(set.isEmpty)
XCTAssertEqual(set.get(at: 0)?.x, nil) XCTAssertEqual(set.get(at: 0)?.x, nil)
XCTAssertEqual(set.get(at: 1)?.x, nil) XCTAssertEqual(set.get(at: 1)?.x, nil)
XCTAssertEqual(set.get(at: 2)?.x, nil) XCTAssertEqual(set.get(at: 2)?.x, nil)
@ -350,7 +340,7 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 5)?.x, nil) XCTAssertEqual(set.get(at: 5)?.x, nil)
XCTAssertEqual(set.get(at: 6)?.x, nil) XCTAssertEqual(set.get(at: 6)?.x, nil)
XCTAssertEqual(set.get(at: 7)?.x, nil) XCTAssertEqual(set.get(at: 7)?.x, nil)
XCTAssertFalse(set.contains(0)) XCTAssertFalse(set.contains(0))
XCTAssertFalse(set.contains(1)) XCTAssertFalse(set.contains(1))
XCTAssertFalse(set.contains(2)) XCTAssertFalse(set.contains(2))
@ -359,7 +349,7 @@ class SparseSetTests: XCTestCase {
XCTAssertFalse(set.contains(5)) XCTAssertFalse(set.contains(5))
XCTAssertFalse(set.contains(6)) XCTAssertFalse(set.contains(6))
XCTAssertFalse(set.contains(7)) XCTAssertFalse(set.contains(7))
XCTAssertEqual(set.sparse[0], nil) XCTAssertEqual(set.sparse[0], nil)
XCTAssertEqual(set.sparse[1], nil) XCTAssertEqual(set.sparse[1], nil)
XCTAssertEqual(set.sparse[2], nil) XCTAssertEqual(set.sparse[2], nil)
@ -368,24 +358,24 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.sparse[5], nil) XCTAssertEqual(set.sparse[5], nil)
XCTAssertEqual(set.sparse[6], nil) XCTAssertEqual(set.sparse[6], nil)
XCTAssertEqual(set.sparse[7], nil) XCTAssertEqual(set.sparse[7], nil)
} }
func testSparseSetRemoveAndAdd() { func testSparseSetRemoveAndAdd() {
testSparseSetRemove() testSparseSetRemove()
let indices: Set<Int> = [0, 30, 1, 21, 78, 56, 99, 3] let indices: Set<Int> = [0, 30, 1, 21, 78, 56, 99, 3]
for idx in indices { for idx in indices {
let pos = Position(x: idx, y: idx) let pos = Position(x: idx, y: idx)
set.insert(pos, at: idx) set.insert(pos, at: idx)
} }
XCTAssertEqual(set.count, indices.count) XCTAssertEqual(set.count, indices.count)
XCTAssertEqual(set.sparse.count, indices.count) XCTAssertEqual(set.sparse.count, indices.count)
XCTAssertEqual(set.dense.count, indices.count) XCTAssertEqual(set.dense.count, indices.count)
XCTAssertFalse(set.isEmpty) XCTAssertFalse(set.isEmpty)
XCTAssertEqual(set.get(at: 0)?.x, 0) XCTAssertEqual(set.get(at: 0)?.x, 0)
XCTAssertEqual(set.get(at: 30)?.x, 30) XCTAssertEqual(set.get(at: 30)?.x, 30)
XCTAssertEqual(set.get(at: 1)?.x, 1) XCTAssertEqual(set.get(at: 1)?.x, 1)
@ -394,17 +384,16 @@ class SparseSetTests: XCTestCase {
XCTAssertEqual(set.get(at: 56)?.x, 56) XCTAssertEqual(set.get(at: 56)?.x, 56)
XCTAssertEqual(set.get(at: 99)?.x, 99) XCTAssertEqual(set.get(at: 99)?.x, 99)
XCTAssertEqual(set.get(at: 3)?.x, 3) XCTAssertEqual(set.get(at: 3)?.x, 3)
} }
func testSparseSetRemoveNonPresent() { func testSparseSetRemoveNonPresent() {
XCTAssertTrue(set.isEmpty) XCTAssertTrue(set.isEmpty)
XCTAssertNil(set.remove(at: 100)) XCTAssertNil(set.remove(at: 100))
XCTAssertTrue(set.isEmpty) XCTAssertTrue(set.isEmpty)
} }
func testSparseSetDoubleRemove() { func testSparseSetDoubleRemove() {
class AClass { } class AClass { }
let set = UnorderedSparseSet<AClass>() let set = UnorderedSparseSet<AClass>()
@ -412,115 +401,111 @@ class SparseSetTests: XCTestCase {
let b = AClass() let b = AClass()
set.insert(a, at: 0) set.insert(a, at: 0)
set.insert(b, at: 1) set.insert(b, at: 1)
XCTAssertEqual(set.sparse.count, 2) XCTAssertEqual(set.sparse.count, 2)
XCTAssertEqual(set.dense.count, 2) XCTAssertEqual(set.dense.count, 2)
XCTAssertEqual(set.count, 2) XCTAssertEqual(set.count, 2)
XCTAssertTrue(set.get(at: 0) === a) XCTAssertTrue(set.get(at: 0) === a)
XCTAssertTrue(set.get(at: 1) === b) XCTAssertTrue(set.get(at: 1) === b)
XCTAssertEqual(set.count, 2) XCTAssertEqual(set.count, 2)
XCTAssertNotNil(set.remove(at: 1)) XCTAssertNotNil(set.remove(at: 1))
XCTAssertEqual(set.count, 1) XCTAssertEqual(set.count, 1)
XCTAssertEqual(set.sparse.count, 1) XCTAssertEqual(set.sparse.count, 1)
XCTAssertEqual(set.dense.count, 1) XCTAssertEqual(set.dense.count, 1)
XCTAssertNil(set.remove(at: 1)) XCTAssertNil(set.remove(at: 1))
XCTAssertEqual(set.count, 1) XCTAssertEqual(set.count, 1)
XCTAssertEqual(set.sparse.count, 1) XCTAssertEqual(set.sparse.count, 1)
XCTAssertEqual(set.dense.count, 1) XCTAssertEqual(set.dense.count, 1)
XCTAssertTrue(set.get(at: 0) === a) XCTAssertTrue(set.get(at: 0) === a)
XCTAssertEqual(set.count, 1) XCTAssertEqual(set.count, 1)
} }
func testSparseSetNonCongiuousData() { func testSparseSetNonCongiuousData() {
var indices: Set<Int> = [0, 30, 1, 21, 78, 56, 99, 3] var indices: Set<Int> = [0, 30, 1, 21, 78, 56, 99, 3]
for idx in indices { for idx in indices {
let pos = Position(x: idx, y: idx) let pos = Position(x: idx, y: idx)
set.insert(pos, at: idx) set.insert(pos, at: idx)
} }
XCTAssertEqual(set.count, indices.count) XCTAssertEqual(set.count, indices.count)
func recurseValueTest() { func recurseValueTest() {
for idx in indices { for idx in indices {
XCTAssertEqual(set.get(at: idx)?.x, idx) XCTAssertEqual(set.get(at: idx)?.x, idx)
XCTAssertEqual(set.get(at: idx)?.y, idx) XCTAssertEqual(set.get(at: idx)?.y, idx)
} }
} }
recurseValueTest() recurseValueTest()
while let idx = indices.popFirst() { while let idx = indices.popFirst() {
let entry = set.remove(at: idx)! let entry = set.remove(at: idx)!
XCTAssertEqual(entry.key, idx) XCTAssertEqual(entry.key, idx)
recurseValueTest() recurseValueTest()
XCTAssertEqual(set.count, indices.count) XCTAssertEqual(set.count, indices.count)
} }
XCTAssertEqual(set.count, indices.count) XCTAssertEqual(set.count, indices.count)
XCTAssertEqual(set.count, 0) XCTAssertEqual(set.count, 0)
} }
func testSparseSetClear() { func testSparseSetClear() {
let num: Int = 100 let num: Int = 100
XCTAssertEqual(set.count, 0) XCTAssertEqual(set.count, 0)
XCTAssertTrue(set.isEmpty) XCTAssertTrue(set.isEmpty)
for idx in 0..<num { for idx in 0..<num {
let pos = Position(x: idx, y: idx) let pos = Position(x: idx, y: idx)
set.insert(pos, at: idx) set.insert(pos, at: idx)
} }
XCTAssertEqual(set.count, num) XCTAssertEqual(set.count, num)
XCTAssertFalse(set.isEmpty) XCTAssertFalse(set.isEmpty)
set.clear() set.clear()
XCTAssertEqual(set.count, 0) XCTAssertEqual(set.count, 0)
XCTAssertTrue(set.isEmpty) XCTAssertTrue(set.isEmpty)
} }
func testSparseSetReduce() { func testSparseSetReduce() {
let characters = UnorderedSparseSet<Character>() let characters = UnorderedSparseSet<Character>()
characters.insert("H", at: 4) characters.insert("H", at: 4)
characters.insert("e", at: 13) characters.insert("e", at: 13)
characters.insert("l", at: 44) characters.insert("l", at: 44)
characters.insert("l", at: 123) characters.insert("l", at: 123)
characters.insert("o", at: 89) characters.insert("o", at: 89)
characters.insert(" ", at: 66) characters.insert(" ", at: 66)
characters.insert("W", at: 77) characters.insert("W", at: 77)
characters.insert("o", at: 55) characters.insert("o", at: 55)
characters.insert("r", at: 90) characters.insert("r", at: 90)
characters.insert("l", at: 34) characters.insert("l", at: 34)
characters.insert("d", at: 140) characters.insert("d", at: 140)
XCTAssertEqual(characters.count, 11) XCTAssertEqual(characters.count, 11)
let string: String = characters.reduce("") { (res, char) in let string: String = characters.reduce("") { res, char in
return res + "\(char)" res + "\(char)"
} }
// NOTE: this tests only dense insertion order, this is no guarantee for the real ordering. // NOTE: this tests only dense insertion order, this is no guarantee for the real ordering.
XCTAssertEqual(string, "Hello World") XCTAssertEqual(string, "Hello World")
} }
} }

View File

@ -5,106 +5,105 @@
// Created by Christian Treffs on 10.05.18. // Created by Christian Treffs on 10.05.18.
// //
import XCTest
@testable import FirebladeECS @testable import FirebladeECS
import XCTest
class SystemsTests: XCTestCase { class SystemsTests: XCTestCase {
var nexus: Nexus! var nexus: Nexus!
var colorSystem: ColorSystem! var colorSystem: ColorSystem!
var positionSystem: PositionSystem! var positionSystem: PositionSystem!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
nexus = Nexus() nexus = Nexus()
colorSystem = ColorSystem(nexus: nexus) colorSystem = ColorSystem(nexus: nexus)
positionSystem = PositionSystem(nexus: nexus) positionSystem = PositionSystem(nexus: nexus)
} }
override func tearDown() { override func tearDown() {
colorSystem = nil colorSystem = nil
positionSystem = nil positionSystem = nil
nexus = nil nexus = nil
super.tearDown() super.tearDown()
} }
func testSystemsUpdate() { func testSystemsUpdate() {
let num: Int = 10_000 let num: Int = 10_000
colorSystem.update() colorSystem.update()
positionSystem.update() positionSystem.update()
let posTraits = positionSystem.family.traits let posTraits = positionSystem.family.traits
XCTAssertEqual(nexus.numEntities, 0) XCTAssertEqual(nexus.numEntities, 0)
XCTAssertEqual(colorSystem.family.memberIds.count, 0) XCTAssertEqual(colorSystem.family.memberIds.count, 0)
XCTAssertEqual(positionSystem.family.memberIds.count, 0) XCTAssertEqual(positionSystem.family.memberIds.count, 0)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, 0) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, 0)
batchCreateEntities(count: num) batchCreateEntities(count: num)
XCTAssertEqual(nexus.numEntities, num) XCTAssertEqual(nexus.numEntities, num)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num)
XCTAssertEqual(colorSystem.family.memberIds.count, num) XCTAssertEqual(colorSystem.family.memberIds.count, num)
XCTAssertEqual(positionSystem.family.memberIds.count, num) XCTAssertEqual(positionSystem.family.memberIds.count, num)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
colorSystem.update() colorSystem.update()
positionSystem.update() positionSystem.update()
XCTAssertEqual(nexus.numEntities, num) XCTAssertEqual(nexus.numEntities, num)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num)
XCTAssertEqual(colorSystem.family.memberIds.count, num) XCTAssertEqual(colorSystem.family.memberIds.count, num)
XCTAssertEqual(positionSystem.family.memberIds.count, num) XCTAssertEqual(positionSystem.family.memberIds.count, num)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
batchCreateEntities(count: num) batchCreateEntities(count: num)
XCTAssertEqual(nexus.numEntities, num * 2) XCTAssertEqual(nexus.numEntities, num * 2)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2)
XCTAssertEqual(colorSystem.family.memberIds.count, num * 2) XCTAssertEqual(colorSystem.family.memberIds.count, num * 2)
XCTAssertEqual(positionSystem.family.memberIds.count, num * 2) XCTAssertEqual(positionSystem.family.memberIds.count, num * 2)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
colorSystem.update() colorSystem.update()
positionSystem.update() positionSystem.update()
XCTAssertEqual(nexus.numEntities, num * 2) XCTAssertEqual(nexus.numEntities, num * 2)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2)
XCTAssertEqual(colorSystem.family.memberIds.count, num * 2) XCTAssertEqual(colorSystem.family.memberIds.count, num * 2)
XCTAssertEqual(positionSystem.family.memberIds.count, num * 2) XCTAssertEqual(positionSystem.family.memberIds.count, num * 2)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
batchDestroyEntities(count: num) batchDestroyEntities(count: num)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num)
XCTAssertEqual(nexus.freeEntities.count, num) XCTAssertEqual(nexus.freeEntities.count, num)
XCTAssertEqual(nexus.numEntities, num) XCTAssertEqual(nexus.numEntities, num)
XCTAssertEqual(colorSystem.family.memberIds.count, num) XCTAssertEqual(colorSystem.family.memberIds.count, num)
XCTAssertEqual(positionSystem.family.memberIds.count, num) XCTAssertEqual(positionSystem.family.memberIds.count, num)
colorSystem.update() colorSystem.update()
positionSystem.update() positionSystem.update()
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num)
XCTAssertEqual(nexus.numEntities, num) XCTAssertEqual(nexus.numEntities, num)
XCTAssertEqual(colorSystem.family.memberIds.count, num) XCTAssertEqual(colorSystem.family.memberIds.count, num)
XCTAssertEqual(positionSystem.family.memberIds.count, num) XCTAssertEqual(positionSystem.family.memberIds.count, num)
XCTAssertEqual(nexus.freeEntities.count, num) XCTAssertEqual(nexus.freeEntities.count, num)
batchCreateEntities(count: num) batchCreateEntities(count: num)
XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2) XCTAssertEqual(nexus.familyMembersByTraits[posTraits]?.count, num * 2)
XCTAssertEqual(nexus.numEntities, num * 2) XCTAssertEqual(nexus.numEntities, num * 2)
XCTAssertEqual(colorSystem.family.memberIds.count, num * 2) XCTAssertEqual(colorSystem.family.memberIds.count, num * 2)
XCTAssertEqual(positionSystem.family.memberIds.count, num * 2) XCTAssertEqual(positionSystem.family.memberIds.count, num * 2)
XCTAssertEqual(nexus.freeEntities.count, 0) XCTAssertEqual(nexus.freeEntities.count, 0)
} }
func createDefaultEntity(name: String?) { func createDefaultEntity(name: String?) {
let e = nexus.create(entity: name) let e = nexus.create(entity: name)
e.assign(Position(x: 1, y: 2)) e.assign(Position(x: 1, y: 2))
@ -116,11 +115,11 @@ class SystemsTests: XCTestCase {
createDefaultEntity(name: nil) createDefaultEntity(name: nil)
} }
} }
func batchDestroyEntities(count: Int) { func batchDestroyEntities(count: Int) {
let family = nexus.family(requiresAll: [Position.self], excludesAll: []) let family = nexus.family(requiresAll: [Position.self], excludesAll: [])
var currentCount = count var currentCount = count
family.iterate { (entity: Entity!) in family.iterate { (entity: Entity!) in
if currentCount > 0 { if currentCount > 0 {
entity.destroy() entity.destroy()
@ -130,19 +129,19 @@ class SystemsTests: XCTestCase {
return return
} }
} }
} }
} }
class ColorSystem { class ColorSystem {
let family: Family let family: Family
init(nexus: Nexus) { init(nexus: Nexus) {
family = nexus.family(requiresAll: [Color.self], excludesAll: []) family = nexus.family(requiresAll: [Color.self], excludesAll: [])
} }
func update() { func update() {
family.iterate { (color: Color!) in family.iterate { (color: Color!) in
color.r = 1 color.r = 1
@ -152,32 +151,31 @@ class ColorSystem {
} }
} }
class PositionSystem { class PositionSystem {
let family: Family let family: Family
var velocity: Double = 4.0 var velocity: Double = 4.0
init(nexus: Nexus) { init(nexus: Nexus) {
family = nexus.family(requiresAll: [Position.self], family = nexus.family(requiresAll: [Position.self],
excludesAll: []) excludesAll: [])
} }
func randNorm() -> Double { func randNorm() -> Double {
return 4.0 return 4.0
} }
func update() { func update() {
family.iterate { [unowned self](pos: Position!) in family.iterate { [unowned self](pos: Position!) in
let deltaX: Double = self.velocity*((self.randNorm() * 2) - 1) let deltaX: Double = self.velocity * ((self.randNorm() * 2) - 1)
let deltaY: Double = self.velocity*((self.randNorm() * 2) - 1) let deltaY: Double = self.velocity * ((self.randNorm() * 2) - 1)
let x = pos.x + Int(deltaX) let x = pos.x + Int(deltaX)
let y = pos.y + Int(deltaY) let y = pos.y + Int(deltaY)
pos.x = x pos.x = x
pos.y = y pos.y = y
} }
} }
} }

View File

@ -11,7 +11,7 @@ bundle install
swift package update swift package update
# generate project # generate project
swift package generate-xcodeproj #--xcconfig-overrides settings.xcconfig swift package generate-xcodeproj --enable-code-coverage #--xcconfig-overrides settings.xcconfig
# add project specialities # add project specialities
bundle exec ./prepareXcodeProject.rb bundle exec ./prepareXcodeProject.rb