Skip to content

Commit

Permalink
int -> BigInt to support more than 32 systems and components
Browse files Browse the repository at this point in the history
  • Loading branch information
denniskaselow committed Nov 14, 2018
1 parent a8b3d5b commit f047651
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 37 deletions.
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ linter:
# - public_member_api_docs
- recursive_getters
- slash_for_doc_comments
- sort_constructors_first
# - sort_constructors_first
- sort_unnamed_constructors_first
- super_goes_last
- test_types_in_equals
Expand Down
14 changes: 7 additions & 7 deletions lib/src/core/aspect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ part of dartemis;
/// is the same as:
/// Aspect.forAllOf([A, B, C])..exclude([U, V])..oneOf([X, Y, Z])
class Aspect {
int _all = 0;
int _excluded = 0;
int _one = 0;
BigInt _all = BigInt.zero;
BigInt _excluded = BigInt.zero;
BigInt _one = BigInt.zero;

/// Creates an aspect where an entity must possess all of the specified
/// components.
Expand Down Expand Up @@ -68,11 +68,11 @@ class Aspect {
_one = _updateBitMask(_one, componentTypes);
}

int get all => _all;
int get excluded => _excluded;
int get one => _one;
BigInt get all => _all;
BigInt get excluded => _excluded;
BigInt get one => _one;

int _updateBitMask(int mask, List<Type> componentTypes) {
BigInt _updateBitMask(BigInt mask, List<Type> componentTypes) {
var result = mask;
if (null != componentTypes) {
componentTypes.forEach((componentType) {
Expand Down
10 changes: 5 additions & 5 deletions lib/src/core/component_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ComponentManager extends Manager {
components[entity.id]._removed();
components[entity.id] = null;
});
entity._typeBits = 0;
entity._typeBits = BigInt.zero;
}

void _addComponent(Entity entity, ComponentType type, Component component) {
Expand All @@ -35,7 +35,7 @@ class ComponentManager extends Manager {
}

void _removeComponent(Entity entity, ComponentType type) {
if ((entity._typeBits & type.bit) != 0) {
if ((entity._typeBits & type.bit) != BigInt.zero) {
final int typeId = type.id;
_componentsByType[typeId][entity.id]._removed();
_componentsByType[typeId][entity.id] = null;
Expand Down Expand Up @@ -73,10 +73,10 @@ class ComponentManager extends Manager {

void _forComponentsOfEntity(
Entity entity, void f(Bag<Component> components, int index)) {
int componentBits = entity._typeBits;
BigInt componentBits = entity._typeBits;
int index = 0;
while (componentBits > 0) {
if ((componentBits & 1) == 1) {
while (componentBits > BigInt.zero) {
if ((componentBits & BigInt.one) == BigInt.one) {
f(_componentsByType[index], index);
}
index++;
Expand Down
8 changes: 4 additions & 4 deletions lib/src/core/component_type.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
part of dartemis;

class ComponentType {
static var _nextBit = 1;
static var _nextId = 0;
static BigInt _nextBit = BigInt.one;
static int _nextId = 0;

var _bit = 0;
var _bit = BigInt.zero;
var _id = 0;

ComponentType() {
Expand All @@ -13,6 +13,6 @@ class ComponentType {
_id = _nextId++;
}

int get bit => _bit;
BigInt get bit => _bit;
int get id => _id;
}
2 changes: 1 addition & 1 deletion lib/src/core/component_type_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ class ComponentTypeManager {
return componentType;
}

static int getBit(Type componentType) => getTypeFor(componentType).bit;
static BigInt getBit(Type componentType) => getTypeFor(componentType).bit;
static int getId(Type componentType) => getTypeFor(componentType).id;
}
12 changes: 6 additions & 6 deletions lib/src/core/entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class Entity {
final int id;

int _uniqueId;
int _typeBits = 0;
int _systemBits = 0;
BigInt _typeBits = BigInt.zero;
BigInt _systemBits = BigInt.zero;

World _world;
EntityManager _entityManager;
Expand All @@ -25,19 +25,19 @@ class Entity {
/// internally use this to identify between different instances.
int get uniqueId => _uniqueId;

void _addTypeBit(int bit) {
void _addTypeBit(BigInt bit) {
_typeBits |= bit;
}

void _removeTypeBit(int bit) {
void _removeTypeBit(BigInt bit) {
_typeBits &= ~bit;
}

void _addSystemBit(int bit) {
void _addSystemBit(BigInt bit) {
_systemBits |= bit;
}

void _removeSystemBit(int bit) {
void _removeSystemBit(BigInt bit) {
_systemBits &= ~bit;
}

Expand Down
18 changes: 9 additions & 9 deletions lib/src/core/entity_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ part of dartemis;
/// There is no need to ever call any other method than process on objects of
/// this class.
abstract class EntitySystem implements EntityObserver {
int _systemBit = 0;
BigInt _systemBit = BigInt.zero;
World _world;
Bag<Entity> _actives;

int _all;
int _excluded;
int _one;
BigInt _all;
BigInt _excluded;
BigInt _one;
bool _dummy;

bool _passive;
Expand All @@ -24,7 +24,7 @@ abstract class EntitySystem implements EntityObserver {
_all = aspect.all,
_excluded = aspect.excluded,
_one = aspect.one {
_dummy = _all == 0 && _one == 0;
_dummy = _all == BigInt.zero && _one == BigInt.zero;
_systemBit = _SystemBitManager._getBitFor(runtimeType);
}

Expand Down Expand Up @@ -79,11 +79,11 @@ abstract class EntitySystem implements EntityObserver {
}
final bool contains = _contains(entity);
bool interest = (_all & entity._typeBits) == _all;
if (_one > 0 && interest) {
interest = (_one & entity._typeBits) > 0;
if (_one > BigInt.zero && interest) {
interest = (_one & entity._typeBits) > BigInt.zero;
}
if (_excluded > 0 && interest) {
interest = (_excluded & entity._typeBits) == 0;
if (_excluded > BigInt.zero && interest) {
interest = (_excluded & entity._typeBits) == BigInt.zero;
}

if (interest && !contains) {
Expand Down
6 changes: 3 additions & 3 deletions lib/src/core/system_bit_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ class _SystemBitManager {
static int _pos = 0;
static var _systemBits;

static int _getBitFor(Type esType) {
_systemBits ??= <Type, int>{};
static BigInt _getBitFor(Type esType) {
_systemBits ??= <Type, BigInt>{};
var bit = _systemBits[esType];

if (bit == null) {
bit = 1 << _pos;
bit = BigInt.one << _pos;
_pos++;
_systemBits[esType] = bit;
}
Expand Down
90 changes: 90 additions & 0 deletions lib/src/core/world.dart
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,93 @@ class World {
_managersBag.forEach((manager) => manager.destroy());
}
}

class PerformanceMeasureWorld extends World {
int framesToMeasure;
final Map<Type, ListQueue<int>> systemTimes = <Type, ListQueue<int>>{};
final Map<Type, ListQueue<int>> processEntityChangesTimes =
<Type, ListQueue<int>>{};

PerformanceMeasureWorld(this.framesToMeasure) {
systemTimes[runtimeType] = ListQueue<int>(framesToMeasure);
}

@override
void process([int group = 0]) {
_frame[group]++;
_time[group] += delta;
_processEntityChanges();
final stopwatch = Stopwatch()..start();
var lastStop = stopwatch.elapsedMicroseconds;
_systemsList
.where((system) => !system.passive && system.group == group)
.forEach((system) {
system.process();
final afterSystem = stopwatch.elapsedMicroseconds;
_processEntityChanges();
final afterProcessEntityChanges = stopwatch.elapsedMicroseconds;
_storeTime(systemTimes, system, afterSystem, lastStop);
_storeTime(processEntityChangesTimes, system, afterProcessEntityChanges,
afterSystem);
lastStop = stopwatch.elapsedMicroseconds;
});
final now = stopwatch.elapsedMicroseconds;
final times = systemTimes[runtimeType];
if (times.length >= framesToMeasure) {
times.removeFirst();
}
times.add(now);
}

void _storeTime(Map<Type, ListQueue<int>> measuredTimes, EntitySystem system,
int afterSystem, int lastStop) {
final times = measuredTimes[system.runtimeType];
if (times.length >= framesToMeasure) {
times.removeFirst();
}
times.add(afterSystem - lastStop);
}

@override
void addSystem(EntitySystem system, {bool passive = false, int group = 0}) {
super.addSystem(system, passive: passive, group: group);
systemTimes[system.runtimeType] = ListQueue<int>(framesToMeasure);
processEntityChangesTimes[system.runtimeType] =
ListQueue<int>(framesToMeasure);
}

List<PerformanceStats> getPerformanceStats() {
final result = <PerformanceStats>[];
_createPerformanceStats(systemTimes, result);
_createPerformanceStats(processEntityChangesTimes, result);
return result;
}

void _createPerformanceStats(
Map<Type, ListQueue<int>> measuredTimes, List<PerformanceStats> result) {
for (final entry in measuredTimes.entries) {
final measurements = entry.value.length;
final sorted = List.from(entry.value)..sort();
final meanTime = sorted[measurements ~/ 2];
final averageTime =
sorted.fold(0, (sum, item) => sum + item) / measurements;
final minTime = sorted.first;
final maxTime = sorted.last;
result.add(PerformanceStats(
entry.key, measurements, minTime, maxTime, averageTime, meanTime));
}
}
}

class PerformanceStats {
Type system;
int measurements;
int minTime, maxTime;
double meanTime, averageTime;
PerformanceStats(this.system, this.measurements, this.minTime, this.maxTime,
this.averageTime, this.meanTime);

@override
String toString() =>
'PerformanceStats{system: $system, measurements: $measurements, minTime: $minTime, maxTime: $maxTime, meanTime: $meanTime, averageTime: $averageTime}';
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ dependencies:
dev_dependencies:
test: ^1.2.0
mockito: ^3.0.0
build_runner: ^0.10.0
build_runner: ^1.0.0
build_web_compilers: ^0.4.0

0 comments on commit f047651

Please sign in to comment.